(Translated by https://www.hiragana.jp/)
地理空間情報を扱うなら知っておきたいPythonライブラリ、GeoPandas入門~基礎編~ | 宙畑

宙畑 Sorabatake

衛星えいせいデータ

地理ちり空間くうかん情報じょうほうあつかうならっておきたいPythonライブラリ、GeoPandas入門にゅうもん~基礎きそへん~

さまざまなデータを地理ちり空間くうかん情報じょうほうとして重畳ちょうじょうするじょう有用ゆうようなPythonのライブラリであるGeoPandas。前編ぜんぺんではGeoPandasをもちいたデータの描画びょうが方法ほうほうなど基礎きそてきあつかかた紹介しょうかいし、後編こうへんでは衛星えいせいデータとわせて解析かいせき結果けっか可視かしする方法ほうほう紹介しょうかいします。

Pythonで地理ちり空間くうかん情報じょうほうおこな場合ばあい、GeoPandasの使つかかたおぼえておくととても便利べんりです。

たとえば、都道府県とどうふけんべつ気象きしょうデータをっていたとします。そのテーブルデータ(csv)には地理ちり情報じょうほうえば、都道府県とどうふけん名称めいしょうくらいしかありません。このような場合ばあい、これを日本にっぽん地図ちずうえ重畳ちょうじょうして可視かしすることはできません。

しかし、このデータに地図ちずじょう描画びょうができる情報じょうほうあたえることさえできれば、きなデータを地図ちずうえかさねることができます。このようなことをしたい場合ばあいに、GeoPandasの使つかかたっておけばたすけになります。

今回こんかいは、簡単かんたんれいつうじて、GeoPandasの魅力みりょく一端いったんってみましょう。

今回こんかい解析かいせきではGoogle Colaboratory利用りようしています。ローカルでも動作どうさします。

かりにローカルで実行じっこうする場合ばあいには、いくつかの処理しょり必要ひつようありませんので都度つどスキップしてください。

今回こんかい利用りようするデータはこちら

この前編ぜんぺんでは

  • ・ラスターデータとベクターデータのかえ
  • ・GeoPandasを利用りようしてベクターデータのみや描画びょうが
  • ・csvデータとベクターデータのわせによる解析かいせき
  • ・やや高度こうど描画びょうが方法ほうほう
  • 系列けいれつ動画どうが(タイムラプス動画どうが)の作成さくせい
  • ・Plotlyをもちいた可視かしれい

について紹介しょうかいします。

ラスターとベクター

地理ちり空間くうかん情報じょうほうとはいわゆるGISというものです。まずは基礎きそちゅう基礎きそ画像がぞう形式けいしきとしてラスター、ベクターというものをおもすにめ、この記事きじ後編こうへんでは、実際じっさいにコードをうごかしながら地理ちり空間くうかん情報じょうほう解析かいせき必要ひつよう知識ちしきである、参照さんしょうけい概念がいねん説明せつめいします。
参照さんしょうけいなにになるほうこちらの論文ろんぶんひとしをごらんください

ラスターデータ

Source : National Ecological Observatory Network (NEON)

ラスターデータとはうえのように格子こうしじょうなかにデータがはいったものです。格子こうしおおきさにより、画像がぞうなめらかさがわります。格子こうしこまかいラスターデータは、より解像度かいぞうどたか画像がぞうこうえらられ、格子こうしおおきくなれば、あら画像がぞうになります。

このひとひとつの格子こうしをピクセルとびます。

ラスターはGeoPandasであつかうより、rasterioなどであつかうことがおおいのですが、このピクセル座標ざひょう地理ちり座標ざひょうえ、ピクセルひとひとつをテーブルデータとしてあつかうことができます。とくはじめから地理ちり座標ざひょうそなえているGeoTIFFデータでは、この変換へんかん作業さぎょうはとてもらくです。

Source : National Ecological Observatory Network (NEON)

うえればあきらかです。不鮮明ふせんめい画像がぞうでは、ピクセルのかたちがはっきりとわかりますが、たか解像度かいぞうどのものでは、ピクセルのかたちとらえることができません。

ラスターデータはたん写真しゃしんのようなデータというわけではなく、ピクセルのなかはいっているもちいて発展はってんてき解析かいせきおこないます。代表だいひょうてきなものとして植生しょくせい活性かっせいしめすNDVIやEVIがあります。

に、下図したずのように地表ちひょうめん温度おんど推定すいていもとめることができます。

Credit : sorabatake

ピクセル座標ざひょう地理ちり空間くうかん情報じょうほうふくむと、実際じっさい地図ちずじょうにデータをかさねることができます。

画像がぞう自身じしん自分じぶんがどこにてはまるのかをっていません。ここに参照さんしょうとなるデータをあたえてあげる(georeference)と、画像がぞうデータがどこに位置いちするべきなのかを判断はんだんできます。

ベクターデータ

つづいてベクターです。ベクターはラスターとちがい、格子こうしなかにデータをたない、ピクセルで構築こうちくされていないデータです。

てんのデータ、せんのデータ、そしてポリゴンとばれる多角たかくがたのデータがこれにたります。たとえば、市町村しちょうそん境界きょうかい、Google Mapじょうでおりの場所ばしょとしたピンがベクターデータになります。

Source : National Ecological Observatory Network (NEON)

うえるとわかるように、ポイントは、ひとつの座標ざひょう構成こうせいされています。ラインはすくなくとも2てん情報じょうほう必要ひつようであり、そのせんじていません。ポリゴンでは、複数ふくすうてんせんじることが条件じょうけんとなります。もちろん、えんもポリゴンです。

ベクターファイルの有名ゆうめい形式けいしきとしてはshp(shapefile)があります。GeoJSONも代表だいひょうてきなファイル形式けいしきえるでしょう。ベクターは数学すうがくてき記述きじゅつされたデータであり、解像度かいぞうどという概念がいねんをもっていません。そのため拡大かくだいしても縮小しゅくしょうしても、変化へんかはありません。

GeoPandasをさわってみよう

GeoPandasとはそもそもなになのか。GeoPandasとはPandasによるテーブルデータの処理しょりと、Shapelyによる幾何きかがくてきなデータ処理しょりあわったものになります。そこにmatplotlibによる描画びょうが支援しえんおこなわれているため、地理ちり空間くうかん情報じょうほう簡単かんたんなテーブルデータで処理しょりできるだけでなく、ちょっとしたコマンドで直接ちょくせつ描画びょうがまでおこなえるというまされものです。

Source : GeoPandas developers.

言葉ことば説明せつめいするよりも、るとわかりやすいです。地理ちり空間くうかん情報じょうほう様々さまざま形式けいしきがありますが、それをうえのようなテーブルにしてしまい、shapelyにより処理しょりされる幾何きか情報じょうほうはgeometryというれつ保存ほぞんされています。このようなテーブルデータをGeoDataFrameとびます。

geomtryでは

  • ・PointsまたはMulti-Points
  • ・LinesまたはMulti-Lines
  • ・PolygonsまたはMulti-Polygons

基本きほんてきなオブジェクトとしてあつかわれます。

ColabでGeoPandas+αあるふぁ使つか準備じゅんびをします。下記かきのセルを実行じっこうしてください。

GeoPandasには以下いか依存いぞん関係かんけいがあります。

  • ・numpy
  • ・pandas
  • ・shapely
  • ・fiona
  • ・pyproj

くわしくは公式こうしきリファレンスをごらんください。

# Important library for many geopython libraries
!apt install gdal-bin python-gdal python3-gdal 
# Install rtree - Geopandas requirment
!apt install python3-rtree 
# Install Geopandas
!pip install git+git://github.com/geopandas/geopandas.git
# Install Folium for Geographic data visualization
# !pip install folium
!pip install plotly-express
!pip install --upgrade plotly
!pip install matplotlib-scalebar
# Use EE in Python
!pip install geemap
!pip install ipygee

# Colab使用しよう
import os
os.kill(os.getpid(), 9)

# Colab使用しよう

# Driveのマウント
# Filesからもワンクリックでマウント可能かのうです
from google.colab import drive
drive.mount('/content/drive')

ライブラリのインポートをおこないます。上記じょうきすべてがインストールされていれば、エラーなく実行じっこうできます。

import pandas as pd
import numpy as np
import os
import geopandas as gpd
from shapely.geometry import Point
import matplotlib
import matplotlib.pyplot as plt 
import folium
import plotly_express as px
from datetime import datetime
import geemap
from ipygee import*

データを使つかって実際じっさい解析かいせきをしてみましょう。

今回こんかいは、e-statから初婚しょこん平均へいきん年齢ねんれいのデータをダウロードしたうえ可視かしします。

レイアウトをいじってからダウンロードしてありますが、それ以外いがいにはとく加工かこうはしていません。

初婚しょこん年齢ねんれいデータの

# 階層かいそう適宜てきぎ変更へんこうしてください
marriageDf = pd.read_csv('/content/drive/MyDrive/Sorabatake/marriage.csv')

データの中身なかみ確認かくにんします。

marriageDf.info()

RangeIndex: 680 entries, 0 to 679
Data columns (total 14 columns):
# Column Non-Null Count Dtype
— —— ————– —–
0 cat01_code 680 non-null int64
1 年齢ねんれい(5さい階級かいきゅう) 680 non-null object
2 cat02_code 680 non-null int64
3 世帯せたいおも仕事しごと 680 non-null object
4 cat03_code 680 non-null int64
5 総数そうすう再掲さいけい 680 non-null object
6 cat04_code 680 non-null int64
7 おっとつま 680 non-null object
8 area_code 680 non-null int64
9 都道府県とどうふけん特別とくべつ指定してい都市とし再掲さいけい) 680 non-null object
10 time_code 680 non-null int64
11 あいだじく(年次ねんじ) 680 non-null object
12 unit 680 non-null object
13 value 680 non-null float64
dtypes: float64(1), int64(6), object(7)
memory usage: 74.5+ KB

こちらはe-statからダウンロードしたものとなります。ダウンロードまえにレイアウトをいじってからダウンロードしてありますが、それ以外いがいにはとく加工かこうはしていません。

ここでは、簡単かんたんなデータクリーニングもふくめてすすめていきましょう。

marriageDf.head()

marriageDf.describe(include='all')

れつめい変更へんこうします。

marriageDf = marriageDf.loc[:,['おっとつま','都道府県とどうふけん特別とくべつ指定してい都市とし再掲さいけい)','時間じかんじく(年次ねんじ)','value']].\
rename(columns={'おっとつま':'sex','都道府県とどうふけん特別とくべつ指定してい都市とし再掲さいけい)':'prefecture','時間じかんじく(年次ねんじ)':'year','value':'avgAge'}).copy()

つづいて、編集へんしゅうします。

具体ぐたいてきには、

  • おっとはmale、つまはfemale
  • ・xxxxねんからとし削除さくじょ
  • 都道府県とどうふけんレベルのみ抽出ちゅうしゅつ

します。

marriageDf.sex = marriageDf.sex.replace('おっと','male',regex=False).replace('つま','female',regex=False)
marriageDf.year = marriageDf.year.replace('とし$','',regex=True)
# marriageDf.year = pd.to_datetime(marriageDf.year, format = '%Y').dt.to_period('y')
marriageDf.year = marriageDf.year.astype('int64')

includeStr = ['けん$','みち$','$','$']
marriageDf = marriageDf.loc[marriageDf.prefecture.str.contains('|'.join(includeStr)),:].reset_index(drop=True)

marriageDf.describe(include='all') # describe all variables

初婚しょこん年齢ねんれいもっとひくさがしてみましょう。

marriageDf.loc[marriageDf.avgAge == marriageDf.avgAge.min(),:]

佐賀さがけんの28.5さい表示ひょうじされます。

初婚しょこん年齢ねんれいもっとたかさがしてみましょう。

marriageDf.loc[marriageDf.avgAge == marriageDf.avgAge.max(),:]

東京とうきょうの32.5さい表示ひょうじされます。

つまり、都道府県とどうふけんレベルでると、佐賀さがけんもっとはやく、東京とうきょうもっとおそ結婚けっこんしていることがわかります。

ベクターファイルの

GADMからファイルをダウンロードします。

シェープファイルをダウンロードし、解凍かいとうすると以下いかのファイルがふくまれています。

  • ・.cpg
  • ・.dbf
  • ・.prj
  • ・.shp
  • ・.shx

です。geopandasではシェープファイルをさいに、.shpしか指定していしません。しかし、GeoPandasでデータをむためには、.shp、.dbf、そして.shxはおなじフォルダに存在そんざいしている必要ひつようがあります。かりにこれらのファイルがけてしまっている場合ばあい、pythonはエラーをかえします。解凍かいとうしたファイルからshpだけをのこしてのファイルを削除さくじょしないようにしましょう。

# 階層かいそう適宜てきぎ変更へんこうしてください
jpnShp = gpd.read_file('/content/drive/MyDrive/Sorabatake/japanSHP/gadm36_JPN_1.shp')

jpnShp.head()

今回こんかい行政ぎょうせいレベル1を利用りようしているため、都道府県とどうふけんレベルでのデータを利用りようすることができます。

データフレームないでgeometryのれつ地図ちずじょう対象たいしょう描画びょうがするために必要ひつよう情報じょうほうになります。

geopandasではフィルタリングもおものです。Pandasにれている場合ばあいには、問題もんだいなくデータのクリーニングがおこなえます。データの操作そうさおこなまえに、簡単かんたん可視かしおこなってみましょう。

以下いかの3ぎょうのコマンドで描画びょうがすることが可能かのうです。

ax = jpnShp.plot(figsize=(10, 10))
jpnShp.plot(ax=ax)
plt.show();
Credit : sorabatake

今回こんかい都道府県とどうふけんレベルのデータを利用りようしていますので、境界きょうかい描画びょうがします。

あわせて、名前なまえ重畳ちょうじょうします。

# 日本にっぽんのシェープデータを可視かしする
ax = jpnShp.plot(figsize=(14, 14))
jpnShp.apply(lambda x: ax.annotate(s=x.NAME_1, xy=x.geometry.centroid.coords[0], ha='center', color = 'black', size = 6),axis=1)
jpnShp.plot(ax = ax, edgecolors='black')
plt.title('Administrative level 1 map in Japan', fontsize=16)
plt.show();
Credit : sorabatake

GeoDataFramedではShapelyとmatplotlibにより、簡単かんたんにベクターデータを可視かしすることができます。それでは、このさきほど取得しゅとくしたe-statのデータを結合けつごうし、さらに描画びょうがおこないます。

shpとcsvの結合けつごう

シェープファイルのようなデータは、地図ちずじょうにデータを投影とうえいするために必要ひつようなデータをすでっています。たんなるテーブルデータは、このようなデータをっていません。しかし、今回こんかいのシェープファイルは都道府県とどうふけんかたち描画びょうがする以上いじょうのデータをふくんでいません。

たとえば、果物くだもの都道府県とどうふけんべつ収穫しゅうかくりょうのデーブルデータをっているとして、一方いっぽうでこのデータには地図ちずじょうにデータをえがくための情報じょうほうふくまれていません。このような場合ばあいうえしめしたシェープファイルを利用りようすれば、果物くだもの収穫しゅうかくりょうった都道府県とどうふけんのデータ(GeoDataFrame)が作成さくせいできます。

今回こんかいは、平均へいきん初婚しょこん年齢ねんれいですが、やることはおなじです。早速さっそくためしてみましょう。

# 必要ひつようれつ削除さくじょ
japan = jpnShp.loc[:,['NAME_1','NL_NAME_1','geometry']].copy()

combDf = japan.merge(marriageDf,left_on='NL_NAME_1',right_on='prefecture',how='left') # データの結合けつごう
combDf.head() # check

再度さいど描画びょうがおこないます。今度こんどは、2019ねん平均へいきん初婚しょこん年齢ねんれい日本にっぽん地図ちず重畳ちょうじょうします。

from matplotlib_scalebar.scalebar import ScaleBar
from mpl_toolkits.axes_grid1 import make_axes_locatable

縮尺しゅくしゃく方位ほういれないとGISさんにおこられるので、わすれないようにしましょう。

Pythonで縮尺しゅくしゃくれるためには、ScaleBar利用りようするのがいです(Cartopyを使つかえばもっと正確せいかくです)。
個人こじんてきにはPythonでの縮尺しゅくしゃく追加ついか面倒めんどうです。もっとシンプルに論文ろんぶん使つかえる、プレゼンで使つかえる地理ちり空間くうかん情報じょうほう可視かしであればRのほうらく実行じっこうできます。

ScaleBarでは1ピクセルあたりのながさと、そのたんにを指定していする必要ひつようがあります。今回こんかいは50とkmを指定していしていますので、1ピクセルあたり50kmという計算けいさんになります。またながさは、 1, 2, 5, 10, 15, 20, 25, 50, 75, 100, 125, 150, 200, 500 or 750のみしかあつかえませんので、縮尺しゅくしゃく実際じっさいながさにはややずれがしょうじることがかんがえられます。こまかい精度せいどまでにしなければならない場合ばあいには、自分じぶん緯度いど経度けいどもとにして距離きょり算出さんしゅつして縮尺しゅくしゃくつくるのがいとおもいます。

# 男性だんせい
# 方位ほうい作成さくせいについての参考さんこう記事きじ:
## https://mohammadimranhasan.com/geospatial-data-mapping-with-python/
combDf2019M = combDf.loc[(combDf.year == 2019)&(combDf.sex == 'male'),:].reset_index(drop=True).copy()
ax = combDf2019M.plot(figsize=(16, 16))
scalebar = ScaleBar(50, location='lower right',units='km')
ax.add_artist(scalebar) # 200km
ax.text(x=153.215-0.55, y=40.4, s='N', fontsize=30) # North Arrow
ax.arrow(153.215, 39.36, 0, 1, length_includes_head=True,
          head_width=0.8, head_length=1.5, overhang=.1, facecolor='k') # North Arrow
combDf2019M.apply(lambda x: ax.annotate(s=x.NAME_1, xy=x.geometry.centroid.coords[0], ha='center', color = 'black', size = 6),axis=1)
combDf2019M.plot(column='avgAge', cmap = 'rainbow', edgecolors='black', ax = ax, legend=True,legend_kwds={'label': "Average age of first marriage",'orientation': "vertical"})
plt.title('Average Age of First Marriage among Males by Prefectures in 2019', fontsize=16)
plt.show();
Credit : sorabatake

ると、東京とうきょう平均へいきん初婚しょこん年齢ねんれいたかいことがかります。その一方いっぽう西日本にしにほんがわとく中国ちゅうごく四国しこく九州きゅうしゅう地方ちほうでは平均へいきん初婚しょこん年齢ねんれいがややわかいのがわかるかとおもいます。

このように、たんとしてみるより、地図ちず可視かしするというのは、非常ひじょうにわかりやすく、おおまかな地理ちりてき変異へんいとらえることに役立やくだちます。

くわえて女性じょせいてみましょう。

# 女性じょせい
combDf2019F = combDf.loc[(combDf.year == 2019)&(combDf.sex == 'female'),:].reset_index(drop=True).copy()
ax = combDf2019F.plot(figsize=(16, 16))
scalebar = ScaleBar(50, location='lower right',units='km')
ax.add_artist(scalebar) # 200km
ax.text(x=153.215-0.55, y=40.4, s='N', fontsize=30) # North Arrow
ax.arrow(153.215, 39.36, 0, 1, length_includes_head=True,
          head_width=0.8, head_length=1.5, overhang=.1, facecolor='k') # North Arrow
combDf2019F.apply(lambda x: ax.annotate(s=x.NAME_1, xy=x.geometry.centroid.coords[0], ha='center', color = 'black', size = 6),axis=1)
combDf2019M.plot(column='avgAge', cmap = 'rainbow', edgecolors='black', ax = ax, legend=True,legend_kwds={'label': "Average age of first marriage",'orientation': "vertical"})
plt.title('Average Age of First Marriage among Females by Prefectures in 2019', fontsize=16)
plt.show();
Credit : sorabatake

女性じょせい傾向けいこうおなじですね!

これらのコロプレスマップばれるものです。

5ねんぶんをまとめて描画びょうがします。このようにすることで時間じかんごとの変化へんかかりやすくなります。

combDf2018M = combDf.loc[(combDf.year == 2018)&(combDf.sex == 'male'),:].reset_index(drop=True).copy()
combDf2017M = combDf.loc[(combDf.year == 2017)&(combDf.sex == 'male'),:].reset_index(drop=True).copy()
combDf2016M = combDf.loc[(combDf.year == 2016)&(combDf.sex == 'male'),:].reset_index(drop=True).copy()
combDf2015M = combDf.loc[(combDf.year == 2015)&(combDf.sex == 'male'),:].reset_index(drop=True).copy()

with plt.rc_context(rc={'font.family': 'serif', 'font.weight': 'bold', 'font.size': 12}):
    fig, ((ax1, ax2), (ax3, ax4), (ax5, ax6)) = plt.subplots(nrows=3, ncols=2, figsize = (20,20))
    fig.autofmt_xdate(rotation = 45)
    # 2019
    scalebar = ScaleBar(50, location='lower right',units='km')
    combDf2019M.plot(column='avgAge', cmap = 'rainbow', edgecolors='black', ax = ax1, legend=True,vmin=28.5, vmax=32.5)
    ax1.set_title('Average age of first marriage in 2019', fontsize=10)
    ax1.text(x=152.215-0.85, y=40.7, s='N', fontsize=15) # North Arrow
    ax1.arrow(152.215, 39.36, 0, 1, length_includes_head=True, head_width=0.8, head_length=1.5, overhang=.1, facecolor='k') # North Arrow
    ax1.add_artist(scalebar)
    # 2018
    scalebar = ScaleBar(50, location='lower right',units='km')
    combDf2018M.plot(column='avgAge', cmap = 'rainbow', edgecolors='black', ax = ax2, legend=True,vmin=28.5, vmax=32.5)
    ax2.set_title('Average age of first marriage in 2018', fontsize=10)
    ax2.text(x=152.215-0.85, y=40.7, s='N', fontsize=15) # North Arrow
    ax2.arrow(152.215, 39.36, 0, 1, length_includes_head=True, head_width=0.8, head_length=1.5, overhang=.1, facecolor='k') # North Arrow
    ax2.add_artist(scalebar)
    # 2017
    scalebar = ScaleBar(50, location='lower right',units='km')
    combDf2017M.plot(column='avgAge', cmap = 'rainbow', edgecolors='black', ax = ax3, legend=True, vmin=28.5, vmax=32.5)
    ax3.set_title('Average age of first marriage in 2017', fontsize=10)
    ax3.text(x=152.215-0.85, y=40.7, s='N', fontsize=15) # North Arrow
    ax3.arrow(152.215, 39.36, 0, 1, length_includes_head=True, head_width=0.8, head_length=1.5, overhang=.1, facecolor='k') # North Arrow
    ax3.add_artist(scalebar)
    # 2016
    scalebar = ScaleBar(50, location='lower right',units='km')
    combDf2016M.plot(column='avgAge', cmap = 'rainbow', edgecolors='black', ax = ax4, legend=True, vmin=28.5, vmax=32.5)
    ax4.set_title('Average age of first marriage in 2016', fontsize=10)
    ax4.text(x=152.215-0.85, y=40.7, s='N', fontsize=15) # North Arrow
    ax4.arrow(152.215, 39.36, 0, 1, length_includes_head=True, head_width=0.8, head_length=1.5, overhang=.1, facecolor='k') # North Arrow
    ax4.add_artist(scalebar)
    # 2015
    scalebar = ScaleBar(50, location='lower right',units='km')
    combDf2015M.plot(column='avgAge', cmap = 'rainbow', edgecolors='black', ax = ax5, legend=True, vmin=28.5, vmax=32.5)
    ax5.set_title('Average age of first marriage in 2015', fontsize=10)
    ax5.text(x=152.215-0.85, y=40.7, s='N', fontsize=15) # North Arrow
    ax5.arrow(152.215, 39.36, 0, 1, length_includes_head=True, head_width=0.8, head_length=1.5, overhang=.1, facecolor='k') # North Arrow
    ax5.add_artist(scalebar)
    # Blank
    ax6.axis('off')
    # plt.tight_layout(pad=4)
    plt.show();
Credit : sorabatake

2015〜2019の5年間ねんかんで、傾向けいこうおおきな変化へんかがないことがわかります。

つづけて、とき系列けいれつ動画どうが(タイムラプス動画どうが)を作成さくせいしましょう。地図ちず可視かしでは動画どうがせるほう理解りかいはやかったりします。今回こんかいは5年間ねんかんのデータですが、これが30年間ねんかんのようなながいスケールになると、時間じかん変化へんかしていく様子ようす動画どうがほう理解りかいしやすくなります。

動画どうが作成さくせい手順てじゅんとしては、png画像がぞう作成さくせいし、ffmpeg利用りようします。

maleDf = combDf.loc[combDf.sex == 'male',:] # Extract males' values
dateMin = maleDf['year'].min()
n_years = maleDf['year'].nunique()

# 画像がぞうとアニメーションの参考さんこう記事きじ
## https://qiita.com/croquette0212/items/8ff251d5da77e803c253
## https://medium.com/tech-carnot/time-lapse-choropleth-map-visualization-using-geopandas-8adb77a7d14
for i in range(0,n_years):
    nyear = dateMin + i
    #Get cumulative df till that date
    dfYear = maleDf.loc[maleDf['year'] == nyear,:]

    fig, ax = plt.subplots(1, figsize=(10,8))
    dfYear.plot(column='avgAge',
                cmap='Blues', linewidth=0.8, ax=ax, edgecolor='0.8')
    # remove the axis
    ax.axis('off')
    # add a title
    ax.set_title('Average Age of First Marriage among Males', 
                 fontdict={'fontsize': '25', 'fontweight' : '3'})
    
    # Create colorbar as a legend
    sm = plt.cm.ScalarMappable(cmap='rainbow', 
            norm=plt.Normalize(vmin=dfYear['avgAge'].min(), vmax=dfYear['avgAge'].max()))
    # add the colorbar to the figure
    cbar = fig.colorbar(sm)
    fontsize = 20
    
    # Positions for the date
    date_x = 140
    date_y = 30
    syear = str(nyear)
    ax.text(date_x, date_y, 
            f"{syear}", 
            color='black',
            fontsize=fontsize)
    fig.savefig(f"/content/drive/MyDrive/Sorabatake/videoff/frame_{i:03d}.png", 
                dpi=100, bbox_inches='tight')
    plt.close()

画像がぞう準備じゅんびができました。うえ保存ほぞんフォルダについては、ご自身じしんきなフォルダで問題もんだいありません。

この画像がぞうもちいて、ffmpeg動画どうが作成さくせい開始かいしします。今回こんかいはターミナルのコマンドをちますので、!を先頭せんとうにつけたコマンドを追加ついかしています。

imgDir = '/content/drive/MyDrive/Sorabatake/videoff' # 動画どうが保存ほぞん場所ばしょ

if not os.path.exists(imgDir):
  os.makedirs(imgDir) # フォルダ作成さくせい

# おな動画どうがめいにならないように注意ちゅうい
!ffmpeg -framerate 1 -i "$imgDir/frame_%03d.png" -c:v h264 -r 30 "$imgDir/avgAgevideo.mp4"

作成さくせいした動画どうがはvlcなどの動画どうがソフトで閲覧えつらん可能かのうです。

Plotlyを使つか

描画びょうがとして、さらにPlotlyを利用りようしてみましょう。こちらでは動的どうてき可視かしおこなえるようになります。

fig = px.choropleth(combDf,                            # データフレーム
                     locations="NAME_1",           # 場所ばしょ名称めいしょう取得しゅとく
                     color="avgAge",                     # 色付いろづけするデータ指定してい
                     hover_name="NAME_1",              # マウスホバーで表示ひょうじするデータ
                     animation_frame="year",        # 時間じかんデータ指定してい
                     projection="natural earth",        # 投影とうえいするめん指定してい
                     color_continuous_scale = 'Peach',  # いろ指定してい
                     range_color=[28,33]            # 色付いろづけするデータの範囲はんい指定してい
                     )        
fig.update_geos(
    center=dict(lon=136, lat=37), scope='asia',
    lataxis_range=[28,47], lonaxis_range=[125, 150]
)
fig.show()
# plt.close(fig)
Credit : sorabatake

おもったら、かなしい。日本にっぽん行政ぎょうせい区域くいきふくまれていないのですね。あきらめましょう。

かりにポイントデータをかさねるのであれば、scatterを利用りようしてbubble mapをえがくことができます。

こちらの記事きじをご参照さんしょうください。また、treemapであれば、地図ちず描画びょうがするのとおなじようにかりやすく全体ぜんたいちがいをとらえることができます。そちらをためしてみましょう。

df2019 = combDf.loc[combDf.year == 2019,:]
fig = px.treemap(df2019, path=['prefecture'], values='avgAge', color='avgAge', color_continuous_scale='magma')
fig.show()
Credit : sorabatake

おなじように全体ぜんたいつかみやすいのですが、地理ちりてき変異へんいとらえることがむずかしいため、基本きほんてき地図ちずじょう描画びょうができるのがのぞましいとおもいます。

最後さいごに、まとめて描画びょうがします。

表示ひょうじされるラベルは平均へいきん初婚しょこん年齢ねんれいにしてあります。

import plotly.graph_objects as go
from plotly.subplots import make_subplots

df2018 = combDf.loc[combDf.year == 2018,:]
df2017 = combDf.loc[combDf.year == 2017,:]
df2016 = combDf.loc[combDf.year == 2016,:]
df2015 = combDf.loc[combDf.year == 2015,:]

fig = make_subplots(
    cols = 2, rows = 3,
    column_widths=[0.5, 0.5],
    specs = [[{'type': 'treemap'}, {'type': 'treemap'}],
             [{'type': 'treemap'}, {'type': 'treemap'}],
             [{'type': 'treemap'}, {'type': 'treemap'}]],
    horizontal_spacing = 0.01,
    vertical_spacing = 0.01
)

fig.add_trace(go.Treemap(
    labels = df2019['prefecture'].values,
    parents = df2019['year'].values,
    values =  df2019['avgAge'].values,
    marker=dict(
        colors=df2018['avgAge'],
        colorscale='magma'),
    textinfo = "label+value",
    ),row = 1, col = 1)

fig.add_trace(go.Treemap(
    labels = df2018['prefecture'].values,
    parents = df2018['year'].values,
    values = df2018['avgAge'].values,
    marker=dict(
        colors=df2018['avgAge'],
        colorscale='magma'),
    textinfo = "label+value",
    ),row = 1, col = 2)

fig.add_trace(go.Treemap(
    labels = df2017['prefecture'].values,
    parents = df2017['year'].values,
    values =  df2017['avgAge'].values,
    marker=dict(
        colors=df2017['avgAge'],
        colorscale='magma'),
    textinfo = "label+value",
    ),row = 2, col = 1)

fig.add_trace(go.Treemap(
    labels = df2016['prefecture'].values,
    parents = df2016['year'].values,
    values = df2016['avgAge'].values,
    marker=dict(
        colors=df2016['avgAge'],
        colorscale='magma'),
    textinfo = "label+value",
    ),row = 2, col = 2)

fig.add_trace(go.Treemap(
    labels = df2015['prefecture'].values,
    parents = df2015['year'].values,
    values =  df2015['avgAge'].values,
    marker=dict(
        colors=df2015['avgAge'],
        colorscale='magma'),
    textinfo = "label+value",
    ),row = 3, col = 1)
fig.update_layout(height = 1400, width = 1400, paper_bgcolor="LightSteelBlue")
fig.show()
Credit : sorabatake
Credit : sorabatake

数字すうじるのでかりやすいです。結局けっきょく微妙びみょう差異さいはあるものの、30さいというのがひとつの目安めやすになっているようです。

平均へいきんですので、なかこれよりおそ結婚けっこんするひとはや結婚けっこんするひともいるわけです。いつ結婚けっこんするにしても、家庭かてい円満えんまんでありたいものです。

以上いじょうでGeoPandas入門にゅうもん前編ぜんぺん)をわります。

公式こうしきのドキュメントには様々さまざま情報じょうほう記載きさいされており、かなり勉強べんきょうになるかんじです。GISデータはRでも解析かいせきおこなうことができます。Rでの地理ちり空間くうかん情報じょうほう解析かいせきほう便利べんりなパッケージがそろっており、かゆいところにとどくという印象いんしょうです。一方いっぽうでPythonはこう次元じげん配列はいれつ情報じょうほう効率こうりつよく解析かいせきできるライブラリがある、また専門せんもんせいたか特殊とくしゅなライブラリあり、そこがRにくらべるとつよみかとおもいます。

汎用はんようせいではR、機械きかい学習がくしゅう深層しんそう学習がくしゅう+GISとか気象きしょうデータ解析かいせきならPythonといった具合ぐあいでしょうか。あくまで個人こじんてき感想かんそうです。

汎用はんようてき参考さんこう文献ぶんけん

以下いかはよく利用りようする地理ちり空間くうかん解析かいせきのサイトです。辞書じしょてき使つかえます。

neon
Earth Lab

PythonとGIS

Automating GIS Process

ライブラリ関連かんれん

plotly
GeoPandas

空間くうかん参照さんしょうけいかんして

地理ちり情報じょうほうシステム だいかい 空間くうかん参照さんしょうけい

Rでの地理ちり空間くうかん情報じょうほう解析かいせき

Rを使つかった地理ちり空間くうかんデータの可視かし分析ぶんせき
geocomputation