Automating GIS Processes 2024 写経　Lesson 2 （Geopandas: an introduction 2）


https://qiita.com/t_t_japan/items/9e2cc79b6f9ea8e2b4ba 

上記の続きです。

# Write a subset of data to a file

> In the previous section, we learnt how to write an entire GeoDataFrame to a file. We can also write a filtered subset of a data set to a new file, e.g., to help with processing complex data sets.

> First, isolate the lakes in the input data set (class number 36200, see table above):

今回は、データセットの一部、classが`36200`のデータ（池）だけファイルに保存します。

```
lakes = data_modified[data_modified.CLASS == 36200]
lakes.plot()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/1ad3240e-3afa-4e09-988f-745eaea1ad81.png)

池のデータだけを保存します。
```
lakes.to_file(DATA_DIRECTORY / "finland_topographic_database" / "lakes.shp")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/28c31472-d76a-44ce-8e23-ea8748211ff2.png)

ほんとに池のデータだけ書き込みしたのか、確認します。
できていますね。
```
geopandas.read_file(DATA_DIRECTORY / "finland_topographic_database" / "lakes.shp").plot()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/51bcf4ca-4fd8-4dc3-a67b-776edc7465b2.png)

# Grouping data

> A particularly useful method of (geo)pandas’ data frames is their grouping function: `groupby() <https://pandas.pydata.org/docs/user_guide/groupby.html>`__ can split data into groups based on some criteria, apply a function individually to each of the groups, and combine results of such an operation into a common data structure.
> We have used this function earlier: in Geo-Python, lesson 6.
> We can use grouping here to split our input data set into subsets that relate to each of the CLASSes of terrain cover, then save a separate file for each class.
> Let’s start this by, again, taking a look at how the data set actually looks like:

`groupby()`メソッドでデータをグループ化し、`apply()`メソッドでグループごとに処理を行い、結合する、という処理の流れがあります。

`groupby()`メソッドを使ってみましょう。

classでグループ化するので、その一覧（重複排除）を見ます。
```
data["CLASS"].unique()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/35831884-b408-4ee8-a927-a813bf06639f.png)

> To group data, use the data frame’s groupby() method, supply a column name as a parameter:

`groupby()`メソッドで、classでグループ化します。
```
grouped_data = data_modified.groupby("CLASS")
grouped_data
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/dd78f220-bfb6-461c-9d33-b20eaef3547c.png)

> So, grouped_data is a DataFrameGroupBy object. Inside a GroupBy object, its property groups is a dictionary that works as a lookup table: it records which rows belong to which group. The keys of the dictionary are the unique values of the grouping column:

グループ化の結果は`DataFrameGroupBy`型になります。`DataFrame`と違って表形式では表示できません。プロパティの`groups`は、`dictionary`型で、ユニークなキー（この場合はclass）を持っています。

ただ、よくわからないですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/824d2a59-43b9-4423-84a9-c780cd82c0e3.png)

> However, one can also simply iterate over the entire GroupBy object. Let’s count how many rows of data each group has:

よくわからないので、ループして、各グループのclassと件数を出してみましょう。

```
for key, group in grouped_data:
    print(f"Terrain class {key} has {len(group)} rows.")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/79a1e073-5b28-42ae-b15b-735bff2dde0c.png)

> There are, for instance, 56 lake polygons (class 36200) in the input data set.

池（classは36200）は56個あります。

> To obtain all rows that belong to one particular group, use the get_group() method, which returns a brand-new GeoDataFrame:

特定のグループを参照したいときは、`get_group()` メソッドで。`GeoDataFrame`オブジェクトが返ってきます。

```
lakes = grouped_data.get_group(36200)
lakes
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/8c0b288b-bc88-4582-b658-5fdc3041cc8c.png)

# Write grouped data to separate files

> Now we have all the necessary tools in hand to split the input data into separate data sets for each terrain class, and write the individual subsets to new, separate, files. In fact, the code looks almost too simple, doesn’t it?

では、グループごとに分けたデータをファイルに書き出してみましょう。コードはいたってシンプルです（よね？）

```
for key, group in data_modified.groupby("CLASS"):
    # save the group to a new shapefile
    group.to_file(TOPOGRAPHIC_DATABASE_DIRECTORY / f"terrain_{key}.shp")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/f398a89c-9c3f-4e4a-a09a-201681842ef1.png)

念のため、class 32612（庭）のシェープファイルを表示してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/e8da74a7-c46b-4b5b-9b36-8f614fa3fcca.png)


うん、よくわかりませんね。


# Extra: save summary statistics to CSV spreadsheet

おまけ。

> Whenever the results of an operation on a GeoDataFrame do not include a geometry, the output data frame will automatically become a ‘plain’ pandas.DataFrame, and can be saved to the standard table formats.

> One interesting application of this is to save basic descriptive statistics of a geospatial data set into a CSV table. For instance, we might want to know the area each terrain class covers.

> Again, we start by grouping the input data by terrain classes, and then compute the sum of each classes’ area. This can be condensed into one line of code:

`GeoDataFrame`を加工した結果にgeometryが含まれていない場合、出力は自動的に `pandas.DataFrame`になります。

class ごとに`area`の合計を出してみましょう。
```
area_information = data_modified.groupby("CLASS").area.sum()
area_information
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/a239e193-5516-49f8-98e3-fec3610fcc2f.png)

> We can then save the resulting table into a CSV file using the standard pandas approach we learned about in 

CSVファイルとして保存してみましょう。
```
area_information.to_csv(TOPOGRAPHIC_DATABASE_DIRECTORY / "area_by_terrain_class.csv")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4076503/1b1a2161-f610-4b8a-8f44-054c33b554b7.png)