Pythonのgeopandasを使って、複数の言語特徴に基づいた地図を出力する

# 行いたいこと
松浦年男先生の記事 (https://note.com/yearman/n/n69fa3f2d583d) を大いに参考にしました。

言語地図を出力する場合、複数の特徴に基づいて地図を何枚か出力したいことがある。
例えばこんな感じ。
![IMG_7892.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573180/fb2563dd-0be6-8e8e-5b22-d416e4dc0bc7.jpeg)
柴田武・学生有志編(1977)「奄美徳之島のことばー分布から歴史へ」より引用

ということで、Excelに入力したデータから自動で複数枚の地図を出力してくれるプログラムを組んだ。

```python:map.py
import numpy as np
import math
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt

df = gpd.read_file("africa.geojson")
locations = pd.read_excel("coordinate.xlsx")

prm_list = []

# 5列目以降 (=文法特徴と各言語の値が入っている列) を取得し、リストのリストにする。ここの値は自分のデータによって変えること。
for i in range(4,len(locations.columns)):
    a = locations.iloc[:, i].tolist()
    a = list(set(a))
    a.insert(0,locations.iloc[:, i].name)
    prm_list.append(a)

# カラーマップを取得。cmap(整数値)とすることで、色サイクルのN番目の色を取得できる。10で1サイクルなので、cmap(11)はcmap(1)と同じ値を返す。
cmap = plt.get_cmap("tab10")

# エクセルの空欄値をどう処理するか。この値がTrueなら出力しない。Falseなら出力し、凡例には marker_name の文字列が表示される。
isBlankNeglected = True

with plt.style.context("ggplot"):
    # このループでは、各文法特徴について一つの地図を描画する。
    for prm in prm_list:
        df.plot(figsize=(8,8), edgecolor='black', facecolor='white', linewidth = 0.5);
        i = 0
        # このループでは、各言語の具体的な値を取得し、地図上に描写する。
        for item in prm[1:]:
            if isBlankNeglected == True and type(item)!= str:# NaNをとばす
                pass
            else:
                # NaNならN/Aという名前、それ以外は文法特徴を名前にする。
                if type(item)!= str:
                    label_name = "N/A"
                else:
                    label_name = str(item)
                # query (検索条件) を設定する。
                query = str(prm[0])+ " == " + '"' + str(item) + '"'
                # locations.query(クエリの文字列)とすることで、検索条件に適合する座標情報が取得できる。
                location = locations.query(query)
                plt.scatter(location.longitude, location.latitude, marker='v', s=50, color=cmap(i), alpha=0.8, linewidths = 2, label = label_name)
                plt.legend(bbox_to_anchor=(1, 1), loc='upper right', borderaxespad=0, fontsize=18)
                i += 1

        filename = prm[0]
        plt.savefig(filename + ".png", format="png", dpi=400, bbox_inches='tight', pad_inches=0)
        # plt.show()
        plt.close()
```

# 必要なデータ

+ 文法特徴と座標情報の入ったExcelファイル
+ geojsonなどの地図情報

## Excelファイルの作り方
Excelファイルは ```coordinate.xlsx```という名前にする。
D列目までに文法特徴以外の情報を入力する。
![スクリーンショット 2020-11-26 19.31.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573180/dd4d1a29-2a8d-2f9a-e899-71b95d765183.png)

longitude, latitudeの列に座標を入力する。

画像では都市名、国名、経度、緯度のみを入力しているが、これ以外の情報が増えても (=文法特徴以外の情報がE列以降に続いても) よい。
文法特徴以外の情報の列を増やした場合、プログラムの

```py:map.py
for i in range(4,len(locations.columns)):
```

という部分で文法情報としてE列以降を読み込むようにしているので、ここの数字を変更する (Pythonでは数字は0から数え始めるので、上記のプログラムの4という数字は五番目の列 = E列を意味する)。
ただし、文法特徴の列は、必ず右側に固めること (e.g. E列から文法特徴の列が始まった場合、その右側の列はすべて文法特徴の列であること)。

## 地図データ
日本であれば、国土交通省などからgeojsonのファイルが入手できる。
目的に合わせて、都道府県ごとや市区町村ごとのファイルを入手する。

今回はアフリカのデータを使用した (https://github.com/codeforamerica/click_that_hood/tree/master/public/data )。

# 使用方法
同じフォルダに```map.py```と```coordinate.xlsx```とgeojsonをいれる。
その状態で```map.py```を走らせれば、そのフォルダに地図のpngファイルが出力される。

こんな感じ。
![スクリーンショット 2020-11-26 20.03.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573180/df24d7ed-db2f-1f37-5aea-32a5cd8337f9.png)