Automating GIS Processes 2024 写経　Exercise １（Problems 3）


[前回](https://qiita.com/t_t_japan/items/e88a36ebee546c1dec4b)の続きです。

https://github.com/Automating-GIS-processes-II-2024/exercise-1/blob/main/Exercise-1-problem-3-4.ipynb

# Problems 3 and 4

> A very common task handled by GIS is to convert a list of coordinates into geographic objects. For instance, you might have a table with latitude and longitude values, and want to use the locations in a map. Python is an excellent tool for this kind of a task: it can read data from (almost) any input format (CSV, text, Excel, GPX, various databases).

> In this exercise, we concentrate on reading data using pandas, and on creating geometry objects using shapely. Later on in the course, we will get to know other packages that are better tailored to geographic data, and will also learn how to write data to files, including to GIS file formats.

CSVなどから座標のリストを扱いやすい形（例えばPointとか）に変換することは多々あります。
Pandasを使って、実現します。


## Sample data set

[travel_times_2015_helsinki.txt](https://github.com/Automating-GIS-processes-II-2024/exercise-1/blob/a22f76cbf7d4696fd0ce515b57b11f7b8aba631e//data/travel_times_2015_helsinki.txt)をダウンロードして使用します。このファイルは以下の項目を";"で区切って格納しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/cc90a022-59c5-42e1-8825-6e74dd09e19d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/1f6c7b26-a470-40e6-a6fa-7175fd642942.png)

なお、どういうデータなのか把握していなくても、実習に支障はありません。

## Problem 3: Reading coordinates from a text file, and creating geometries (5 points)

> In this problem, your task is to read data from the file described above, and create two lists of points representing the origins and destinations of the routes described in the data set.

> This task entails multiple steps:
>  - Read the data into a pandas.DataFrame
>  - Discard all unnecessary columns (this is good practice, as it helps reduce the memory footprint of a program)
>  - Create two lists of shapely.geometry.Points

ざっくりいうと、travel_times_2015_helsinki.txtを`pandas.DataFrame`として読み取って、処理に必要な列だけ抜き取って、`origin_points`・`destination_points`というPointのリスト２つを作る、です。

早速作るわけですが、まずは、Google colabのカレントディレクトリにtravel_times_2015_helsinki.txtをアップロードする必要があります。

これは、ドラッグアンドドロップでできます。
https://qiita.com/kazoo04/items/a0bd374199a7783ca0ee#%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89


余談ですが、先頭に ! をつけるとシェルコマンドを実行できます。
https://qiita.com/kazoo04/items/a0bd374199a7783ca0ee#%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89

カレントディレクトリは、/contentでした。
```
!pwd
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/c70d4ed7-8679-429c-ae80-1eaa257bf5c0.png)

### (1)
> First, use pandas to read the file into a variable data. You can revisit lesson 5 of the Geo-Python course and consult the pandas documentation to find the best way to do this.

ファイルを読み込み、先頭５件を表示します。
前述の通り、";"区切りのため、 `sep=";"`とする必要があります。
```
import pandas as pd

data = pd.read_csv("travel_times_2015_helsinki.txt", sep=";")

data.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/54f28adc-457e-4c99-b8e6-e4c45c06d0e9.png)

読み込んだデータの行数・列数を見ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/b3c10ad9-8eba-4320-abc6-a6e54b945f9a.png)

### (2)

> Now, select the 4 columns that contain coordinate information (from_x, from_y, to_x, to_y), and store them in a DataFrame data. (i.e. update the variable data to contain only these four columns).

必要な列だけにします。

```
data  = data[["from_x", "from_y", "to_x", "to_y"]]

data.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/b376cfa1-7308-4163-948c-9f733475ad92.png)

余談ですが、上記のコードの場合、列名の指定を間違えると、`KeyError`になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/535a3000-4d22-42c2-aa8f-a449fb7eed8c.png)

これが嫌な場合は、[pandas.DataFrame.filter](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html)を使いましょう。

`KeyError`にならず、間違った列名は無視されるだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/a8da12ef-17a7-4daa-a1f9-33b2bcdb34b1.png)


### (3)
> Finally, create two lists called origin_points and destination_points that contain shapely.geometry.Point objects created using the coordinates from data.

> In particular, the origin points in origin_points should be based on columns from_x and from_y, and the destination points in destination_points on columns to_x and to_y.

`from_x`・`from_y`列から、`origin_points`という`Point`のリストを作る
`to_x`・`to_y`列から、`destination_points`という`Point`のリストを作る

> There are many ways to achieve this, find two possible approaches below (you can implement either one of them):

やり方はいろいろある。以下２種類、どっちでやってもよい。

> Approach A
> - Create two empty lists for the origin and destination points, respectively
> - Use a for-loop to iterate over the rows of your dataframe:
>   - For each row, create a shapely.geometry.Point object based on the coordinate columns
>   - Append the point object to the origin_points and destination_point lists

>You can consult lesson 6 of Geo-Python to revisit how to loop over the rows of a pandas.DataFrame.

Approach A　forループで一行すつ処理する

> Approach B (more advanced)
> - Make use of the .apply() function of the pandas.DataFrame to operate on all rows at once (see its documentation, HINT: you might want to use the axis parameter)
> - Use the shapely.geometry.Point constructor directly, or wrap it into a lambda function
> - Finally, convert the output pandas.Series into lists

Approach B　`apply()`と lambda関数で一気にやる（こちらのほうが先進的）


今回はApproach Bでやります。`apply()`の結果は`pandas.Series`型（雑に言うとpandasの一次配列）なので、`to_list()`でリストします。
```
from shapely.geometry import Point

origin_points = data.apply(lambda row: Point(row["from_x"], row["from_y"]), axis=1).to_list()
destination_points = data.apply(lambda row: Point(row["to_x"], row["to_y"]), axis=1).to_list()
```


結果確認です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/b7b8007e-281f-40b0-9d37-f176f7b487b3.png)

Problems 4に続きます。