オープンストリートマップを利用したオープンデータの可視化②・GeoJSON

Image from Gyazo

GeoJSON

これまでcsv形式のオープンデータを利用してきました,よりウェブに相性が良いデータ形式があります. それが,JSON形式(.json) です. JSONは,「じぇいそん」と読み,ブラウザで動作するプログラミング言語の JavaScript で用いられるデータ形式ですが, 現在はPythonを始めとした様々なプログラミング言語でサポートされています(Pythonでは辞書に対応する).

下記のCSV形式のデータを例に考えてみましょう.

町名,男,女,総数,世帯数
赤池町,1693,1647,3340,1315
浅田町,2593,2431,5024,2086

上記のデータをJSON形式に変換すると下記になります. JSON形式では,データは string(文字列)value(値) の組で表現されます. 例えば,“町名"という文字列と,“赤池町"という値が組になっていることがわかります. また,[ ] は配列を表しており,0番目の要素に赤池町のデータ,1番目の要素に浅田町のデータが格納されます. 要素は「,」で区切られますが,最後の要素には必要ありません.

json = [
  {
    "町名": "赤池町",
    "男": 1693,
    "女": 1647,
    "総数": 3340,
    "世帯数": 1315
  },                                                                                                                                                                                           
  {                                                                                                                                                                                           
    "町名": "浅田町",
    "男": 2593,
    "女": 2431,
    "総数": 5042,
    "世帯数": 2086
  }
]
print(json[0])
print(json[1])
{'町名': '赤池町', '男': 1693, '女': 1647, '総数': 3340, '世帯数': 1315}
{'町名': '浅田町', '男': 2593, '女': 2431, '総数': 5042, '世帯数': 2086}

このJSON形式を基本として,点,線,多角形などの空間データを表現するために用いられるのが GeoJSON 形式です. GeoJSONは,「じおじぇいそん」と読み, Leefletを始めとした様々な地図サービスで利用可能です.

下記のCSV形式のデータを例に考えてみましょう. 緯度・経度の情報が含まれており,オンライン地図ではとして扱われます.

名称,緯度,経度,説明
休日急病診療所,35.132795,137.042009,日進市中央福祉センター内にある休日急病診療所です.
西部福祉会館,35.12599221,137.0147748,乳幼児室,学習室があります.

上記のCSV形式のデータをGeoJSON形式に変換すると下記になります. 少し複雑に見えますが,JSON形式に従っていることを確認してください. ここでは,空間データの種類を表す typePoint(点) を設定しています. Pointの他にも, LineString(線)Polygon(多角形) などを指定することもできます. また,座標は coordinates で指定していますが,経度・緯度の順番であることに注意してください. その他,名称,説明などの情報は, properties に記載します.

geojson = {
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry":
      {
        "type": "Point",
        "coordinates": [137.042009,35.132795]
      },
      "properties":
      {
        "名称": "休日急病診療所",
        "説明": "日進市中央福祉センター内にある休日急病診療所です."
      }
    },
    {
      "type": "Feature",
      "geometry":
      {
        "type": "Point",
        "coordinates": [137.0147748,35.12599221]
      },
      "properties":
      {
        "名称": "西部福祉会館",
        "説明": "日進市中央福祉センター内にある休日急病診療所です."
      }
    }
  ]
}
print(geojson["features"][0])
print(geojson["features"][1])
{'type': 'Feature', 'geometry': {'type': 'Point', 'coordinates': [137.042009, 35.132795]}, 'properties': {'名称': '休日急病診療所', '説明': '日進市中央福祉センター内にある休日急病診療所です.'}}
{'type': 'Feature', 'geometry': {'type': 'Point', 'coordinates': [137.0147748, 35.12599221]}, 'properties': {'名称': '西部福祉会館', '説明': '日進市中央福祉センター内にある休日急病診療所です.'}}

今回はGeoJSON形式に変換したオープンデータとオープンストリートマップを組み合わせ, 前回と同様のオンライン地図を作成する方法について学習していきましょう.

バス停の地図

それでは,Google Colaboratoryを利用して,オープンストリートマップを利用して日進市のバス停の地図を作成しましょう.

ノートブックの作成

まずは,ノートブックを作成します. ノートブックの名前は chapter4.ipynb に設定します.

Image from Gyazo

前回と同様にfoliumをインストールし, foliumpandasをインポートします.

!pip install folium
import folium
import pandas as pd

データフレーム(pandas)

pandasを利用して, CSV形式のオープンデータ(bus_stops.csv)を読み込みます. 日進市のバス停の一覧です.

# bus_stops.csv
url = "https://mukai-lab.info/classes/seminar_fundamental_areas/csv/bus_stops.csv"

# データフレームの生成
df = pd.read_csv(url)

# HTMLで表示(=display(df))
df

Image from Gyazo

ここでは,バス停名緯度経度 の列を抽出します.

df = df[["バス停名", "緯度", "経度"]]
df

Image from Gyazo

地図の中心を,全てのバス停の緯度・経度の平均に設定します. 前回と同じ方法で求めると,中心の緯度は35.1373,経度は137.0466になりました.

center_lat = df[["緯度"]].mean().values[0]
center_lon = df[["経度"]].mean().values[0]

print(f"center_lat={center_lat} center_lon={center_lon}")
center_lat=35.1372590495031 center_lon=137.04657202546582

GeoJSONへの変換

データフレームをGeoJSON形式に変換します. バス停の名前はname,バス停の緯度・経度はlatlonに代入しています. これらの値をfeaturegeometry.coordinatesproperties.nameに設定します.

geojson = {
  "type": "FeatureCollection",
  "features": []
}

for index, row in df.iterrows():
  name = row[0]
  lat = row[1]
  lon = row[2]

  feature = {
    "type": "Feature",
    "geometry": {
      "type": "Point",
      "coordinates": [lon, lat]
    },
    "properties":{
      "name": name
    }
  }

  geojson["features"].append(feature)
print(geojson["features"][0])
print(geojson["features"][1])
{'type': 'Feature', 'geometry': {'type': 'Point', 'coordinates': [137.0394341, 35.13220467]}, 'properties': {'name': '市役所'}}
{'type': 'Feature', 'geometry': {'type': 'Point', 'coordinates': [137.042486, 35.13206576]}, 'properties': {'name': '図書館'}}

オープンストリートマップの表示

先に計算した緯度・経度を中心として地図を表示します. スケール(倍率)は15に設定します.

map = folium.Map(location=[center_lat, center_lon], zoom_start=15)
map

Image from Gyazo

GeoJSON形式のデータを表示するには,GeoJson()を用います. このとき,tooltipとして,バス停の名前を表示します(GeoJsonTooltipを利用します).

map = folium.Map(location=[center_lat, center_lon], zoom_start=15)

tooltip = folium.features.GeoJsonTooltip(fields=["name"], labels=False)
folium.GeoJson(geojson, tooltip=tooltip).add_to(map)

map

この結果,バス停がマーカーとして表示されていることを確認できます.

Image from Gyazo

本日のノートブックは下記URLで確認できます.

chapter4.ipynb

課題

Google Colaboratoryで作成した chapter4.ipynb を保存し, 共有用のリンクノートブック(.ipynb) をダウンロードして提出しなさい. 提出の前に必ず下記の設定を行うこと.

参考書籍

愛知県名古屋市にある椙山女学園大学 文化情報学部 向研究室の公式サイトです. 専門は情報科学であり,人工知能やデータベースなどの技術要素を指導しています. この公式サイトでは,授業で使用している教材を公開すると共に, ベールに包まれた女子大教員のミステリアスな日常を4コマ漫画でお伝えしていきます. サイトに関するご意見やご質問はFacebookまたはTwitterでお問い合わせください.