前準備
pythonがすでにある状態から、matplotlibとpandas、geopandasをインストールするだけです。
Appli Siliconの場合、geopandasの依存するライブラリがうまく動かなかったりするのでゴニョゴニョしていますが、
それ以外の環境では基本的にpip install コマンド一発でインストールできると思います。
実行環境
$ python --version
Python 3.9.4+
$ uname -a
Darwin Iharas-Air 20.5.0 Darwin Kernel Version 20.5.0: Sat May 8 05:10:31 PDT 2021; root:xnu-7195.121.3~9/RELEASE_ARM64_T8101 arm64
matplotlibのインストール
$ pip install matplotlib
$ python
>>> import matplotlib as mpl # 動作チェック
pandasのインストール
$ pip install pandas
$ python
>>> import pandas as pd # 動作チェック
geopandasのインストール
$ brew install gdal proj geos # これはMacの方法です。各プラットフォームに対応する方法でインストールしてください。
$ pip install geopandas
$ python
>>> import geopandas as gpd # 動作チェック
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/taisyo/.pyenv/versions/3.9-dev/lib/python3.9/site-packages/geopandas/__init__.py", line 1, in <module>
from geopandas._config import options # noqa
File "/Users/taisyo/.pyenv/versions/3.9-dev/lib/python3.9/site-packages/geopandas/_config.py", line 126, in <module>
default_value=_default_use_pygeos(),
File "/Users/taisyo/.pyenv/versions/3.9-dev/lib/python3.9/site-packages/geopandas/_config.py", line 112, in _default_use_pygeos
import geopandas._compat as compat
File "/Users/taisyo/.pyenv/versions/3.9-dev/lib/python3.9/site-packages/geopandas/_compat.py", line 10, in <module>
import shapely.geos
File "/Users/taisyo/.pyenv/versions/3.9-dev/lib/python3.9/site-packages/shapely/geos.py", line 136, in <module>
_lgeos = load_dll('geos_c', fallbacks=alt_paths)
File "/Users/taisyo/.pyenv/versions/3.9-dev/lib/python3.9/site-packages/shapely/geos.py", line 60, in load_dll
raise OSError(
OSError: Could not find lib geos_c or load any of its variants ['/Library/Frameworks/GEOS.framework/Versions/Current/GEOS', '/opt/local/lib/libgeos_c.dylib', '/usr/local/lib/libgeos_c.dylib'].
importできない。
shapelyのissueに上がっている問題で、Apple SilcionのMacだとHomebrewのインストール先が変わって、dylibを読み込めないだけなので、dylibのパスを指定している部分を修正する。
$ cd /Users/taisyo/.pyenv/versions/3.9-dev/lib/python3.9/site-packages/shapely
$ cp geos.py geos.org.py
$ vi geos.py
$ diff -U 2 geos.py geos.org.py
--- geos.py 2021-06-17 19:05:42.000000000 +0900
+++ geos.org.py 2021-06-17 19:05:33.000000000 +0900
@@ -133,6 +133,4 @@
# homebrew
'/usr/local/lib/libgeos_c.dylib',
- # homebrew Apple Silicon
- '/opt/homebrew/lib/libgeos_c.dylib',
]
_lgeos = load_dll('geos_c', fallbacks=alt_paths
$ cd
$ python
>>> import geopandas as gpd # 動作チェック
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/taisyo/.pyenv/versions/3.9-dev/lib/python3.9/site-packages/geopandas/__init__.py", line 7, in <module>
from geopandas.io.file import _read_file as read_file # noqa
File "/Users/taisyo/.pyenv/versions/3.9-dev/lib/python3.9/site-packages/geopandas/io/file.py", line 20, in <module>
from fiona import Env as fiona_env
File "/Users/taisyo/.pyenv/versions/3.9-dev/lib/python3.9/site-packages/fiona/__init__.py", line 85, in <module>
with fiona._loading.add_gdal_dll_directories():
AttributeError: partially initialized module 'fiona' has no attribute '_loading' (most likely due to a circular import)
やはりimportできない。エラーメッセージは変わっている。
fionaのissueに上がっている問題で、Apple SilcionのMacだと起きる似たような問題らしい、fionaを先にimportすると治るらしいのでそうしして使う。
>>> import fiona
>>> import geopandas as gpd
geopandas入った!
移行のPythonコードは、下記のような感じで、pandas, geopandas, matplotlibを読み込んでいる前提で話していきます。
>>> import pandas as pd
>>> import fiona
>>> import geopandas as gpd
>>> import matplotlib.pyplot as plt
これで事前準備OK!
都道府県コードを都道府県名に変換しよう!
都道府県ごとの情報をまとめたオープンデータとかAPIでは、直接都道府県名を記述せず、都道府県名を表す都道府県コードで都道府県を表していることがあります。
これはデータの突き合わせの差異不便なので、相互に変換できるようにコードを用意しておきます。
https://nlftp.mlit.go.jp/ksj/gml/codelist/PrefCd.html を気合で辞書にします。
>>> pref_code2name = {
... 1: "北海道",
... 2: "青森県", 3: "岩手県", 4: "宮城県", 5: "秋田県", 6: "山形県", 7: "福島県",
... 8: "茨城県", 9: "栃木県", 10: "群馬県", 11: "埼玉県", 12: "千葉県", 13: "東京都", 14: "神奈川県",
... 15: "新潟県", 16: "富山県", 17: "石川県", 18: "福井県", 19: "山梨県", 20: "長野県", 21: "岐阜県", 22: "静岡県", 23: "愛知県",
... 24: "三重県", 25: "滋賀県", 26: "京都府", 27: "大阪府", 28: "兵庫県", 29: "奈良県", 30: "和歌山県",
... 31: "鳥取県", 32: "島根県", 33: "岡山県", 34: "広島県", 35: "山口県",
... 36: "徳島県", 37: "香川県", 38: "愛媛県", 39: "高知県",
... 40: "福岡県", 41: "佐賀県", 42: "長崎県", 43: "熊本県", 44: "大分県", 45: "宮崎県", 46: "鹿児島県",
... 47: "沖縄県",
... }
>>>
>>> pref_name2code = dict([(v, k) for (k, v) in pref_code2name.items()])
こんな感じで変換できるようになります。
>>> pref_code2name[13]
'東京都'
>>> pref_name2code['東京都']
13
都道府県の地形データを読み込もう!
都道府県の地形データは海外のGADMというプロジェクトが公開しているようなので、これを使います。(国土地理院がこういうのを使いやすい形で提供してくれていたら教えてほしい)
ダウンロードして展開します。
$ curl -L https://biogeo.ucdavis.edu/data/gadm3.6/shp/gadm36_JPN_shp.zip -o gadm36_JPN_shp.zip
$ unzip gadm36_JPN_shp.zip
$ ls
gadm36_JPN_0.cpg gadm36_JPN_0.prj gadm36_JPN_0.shx gadm36_JPN_1.dbf gadm36_JPN_1.shp gadm36_JPN_2.cpg gadm36_JPN_2.prj gadm36_JPN_2.shx
gadm36_JPN_0.dbf gadm36_JPN_0.shp gadm36_JPN_1.cpg gadm36_JPN_1.prj gadm36_JPN_1.shx gadm36_JPN_2.dbf gadm36_JPN_2.shp
読み込みます。
>>> df_jpn = gpd.read_file('gadm36_JPN_1.shp')
>>> df_jpn
GID_0 NAME_0 GID_1 ... CC_1 HASC_1 geometry
0 JPN Japan JPN.1_1 ... None JP.AI MULTIPOLYGON (((137.00780 34.65997, 137.00803 ...
1 JPN Japan JPN.2_1 ... None JP.AK MULTIPOLYGON (((139.55725 39.20330, 139.55765 ...
2 JPN Japan JPN.3_1 ... None JP.AO MULTIPOLYGON (((140.33719 41.04913, 140.33714 ...
3 JPN Japan JPN.4_1 ... None JP.CH MULTIPOLYGON (((139.82487 34.98967, 139.82434 ...
4 JPN Japan JPN.5_1 ... None JP.EH MULTIPOLYGON (((132.55859 32.91224, 132.55904 ...
5 JPN Japan JPN.6_1 ... None JP.FI MULTIPOLYGON (((136.04195 35.73417, 136.04167 ...
6 JPN Japan JPN.7_1 ... None JP.FO MULTIPOLYGON (((130.47037 33.86395, 130.47119 ...
7 JPN Japan JPN.8_1 ... None JP.FS MULTIPOLYGON (((140.79611 36.85653, 140.79472 ...
8 JPN Japan JPN.9_1 ... None JP.GF POLYGON ((137.60454 35.38891, 137.59399 35.386...
9 JPN Japan JPN.10_1 ... None JP.GM POLYGON ((139.50237 36.18904, 139.49628 36.188...
10 JPN Japan JPN.11_1 ... None JP.HS MULTIPOLYGON (((132.48372 34.03422, 132.48318 ...
11 JPN Japan JPN.12_1 ... None JP.HK MULTIPOLYGON (((140.09169 41.41886, 140.09129 ...
12 JPN Japan JPN.13_1 ... None JP.HG MULTIPOLYGON (((134.82297 34.17979, 134.82336 ...
13 JPN Japan JPN.14_1 ... None JP.IB MULTIPOLYGON (((140.69528 35.92944, 140.69444 ...
14 JPN Japan JPN.15_1 ... None JP.IS MULTIPOLYGON (((136.90479 37.40308, 136.90524 ...
15 JPN Japan JPN.16_1 ... None JP.IW MULTIPOLYGON (((141.72762 39.03545, 141.72708 ...
16 JPN Japan JPN.17_1 ... None JP.KG MULTIPOLYGON (((133.53694 34.12017, 133.53493 ...
17 JPN Japan JPN.18_1 ... None JP.KS MULTIPOLYGON (((128.43361 27.06861, 128.43388 ...
18 JPN Japan JPN.19_1 ... None JP.KN MULTIPOLYGON (((139.61588 35.13718, 139.61618 ...
19 JPN Japan JPN.20_1 ... None JP.KC MULTIPOLYGON (((132.48972 32.74389, 132.49028 ...
20 JPN Japan JPN.21_1 ... None JP.KM MULTIPOLYGON (((130.15723 32.08556, 130.15695 ...
21 JPN Japan JPN.22_1 ... None JP.KY POLYGON ((136.02983 34.81502, 136.01799 34.805...
22 JPN Japan JPN.23_1 ... None JP.ME MULTIPOLYGON (((136.29361 34.08222, 136.29361 ...
23 JPN Japan JPN.24_1 ... None JP.MG MULTIPOLYGON (((140.90611 38.03583, 140.90639 ...
24 JPN Japan JPN.25_1 ... None JP.MZ MULTIPOLYGON (((131.41295 31.54124, 131.41327 ...
25 JPN Japan JPN.26_1 ... None JP.NN POLYGON ((137.65213 35.21122, 137.64482 35.205...
26 JPN Japan JPN.27_1 ... None JP.NS MULTIPOLYGON (((128.35547 32.00866, 128.35594 ...
27 JPN Japan JPN.28_1 ... None JP.NR POLYGON ((135.86241 33.89688, 135.84920 33.893...
28 JPN Japan JPN.29_1 ... None JP.NI MULTIPOLYGON (((138.33722 38.20028, 138.33640 ...
29 JPN Japan JPN.30_1 ... None JP.OT MULTIPOLYGON (((131.92316 32.72695, 131.92377 ...
30 JPN Japan JPN.31_1 ... None JP.OY MULTIPOLYGON (((133.54041 34.30756, 133.53979 ...
31 JPN Japan JPN.32_1 ... None JP.ON MULTIPOLYGON (((123.78792 24.07208, 123.78792 ...
32 JPN Japan JPN.33_1 ... None JP.OS MULTIPOLYGON (((135.31573 34.43310, 135.31544 ...
33 JPN Japan JPN.34_1 ... None JP.SG MULTIPOLYGON (((129.77444 33.49556, 129.77499 ...
34 JPN Japan JPN.35_1 ... None JP.ST POLYGON ((139.84909 35.79491, 139.84793 35.795...
35 JPN Japan JPN.36_1 ... None JP.SH POLYGON ((136.28865 34.86865, 136.27882 34.869...
36 JPN Japan JPN.37_1 ... None JP.SM MULTIPOLYGON (((131.83215 34.83653, 131.83249 ...
37 JPN Japan JPN.38_1 ... None JP.SZ MULTIPOLYGON (((141.46085 24.24579, 141.46115 ...
38 JPN Japan JPN.39_1 ... None JP.TC POLYGON ((139.49724 36.27460, 139.48871 36.272...
39 JPN Japan JPN.40_1 ... None JP.TS MULTIPOLYGON (((134.36798 33.58724, 134.36761 ...
40 JPN Japan JPN.41_1 ... None JP.TK MULTIPOLYGON (((139.74005 35.54153, 139.74028 ...
41 JPN Japan JPN.42_1 ... None JP.TT MULTIPOLYGON (((134.22307 35.19029, 134.21843 ...
42 JPN Japan JPN.43_1 ... None JP.TY POLYGON ((136.78896 36.33339, 136.79283 36.341...
43 JPN Japan JPN.44_1 ... None JP.WK MULTIPOLYGON (((135.82077 33.45090, 135.82062 ...
44 JPN Japan JPN.45_1 ... None JP.YT MULTIPOLYGON (((139.68417 38.72306, 139.68333 ...
45 JPN Japan JPN.46_1 ... None JP.YC MULTIPOLYGON (((132.48804 33.73760, 132.48842 ...
46 JPN Japan JPN.47_1 ... None JP.YN POLYGON ((138.52417 35.19426, 138.52386 35.193...
[47 rows x 11 columns]
このdataframeは、都道府県コードがないため、後での突き合わせを考えて、都道府県名のカラムNL_NAME_1から都道府県コードを生成しておきます。
>>> df_jpn['都道府県コード'] = df_jpn['NL_NAME_1'].map(pref_name2code.get)
>>> df_jpn
GID_0 NAME_0 GID_1 NAME_1 VARNAME_1 NL_NAME_1 TYPE_1 ENGTYPE_1 CC_1 HASC_1 geometry 都道府県コード
0 JPN Japan JPN.1_1 Aichi Aiti 愛知県 Ken Prefecture None JP.AI MULTIPOLYGON (((137.00780 34.65997, 137.00803 ... 23
1 JPN Japan JPN.2_1 Akita None 秋田県 Ken Prefecture None JP.AK MULTIPOLYGON (((139.55725 39.20330, 139.55765 ... 5
2 JPN Japan JPN.3_1 Aomori None 青森県 Ken Prefecture None JP.AO MULTIPOLYGON (((140.33719 41.04913, 140.33714 ... 2
3 JPN Japan JPN.4_1 Chiba Tiba|Tsiba 千葉県 Ken Prefecture None JP.CH MULTIPOLYGON (((139.82487 34.98967, 139.82434 ... 12
4 JPN Japan JPN.5_1 Ehime None 愛媛県 Ken Prefecture None JP.EH MULTIPOLYGON (((132.55859 32.91224, 132.55904 ... 38
5 JPN Japan JPN.6_1 Fukui Hukui 福井県 Ken Prefecture None JP.FI MULTIPOLYGON (((136.04195 35.73417, 136.04167 ... 18
6 JPN Japan JPN.7_1 Fukuoka Hukuoka 福岡県 Ken Prefecture None JP.FO MULTIPOLYGON (((130.47037 33.86395, 130.47119 ... 40
7 JPN Japan JPN.8_1 Fukushima Hukusima 福島県 Ken Prefecture None JP.FS MULTIPOLYGON (((140.79611 36.85653, 140.79472 ... 7
8 JPN Japan JPN.9_1 Gifu Gihu 岐阜県 Ken Prefecture None JP.GF POLYGON ((137.60454 35.38891, 137.59399 35.386... 21
9 JPN Japan JPN.10_1 Gunma GunmaGumma 群馬県 Ken Prefecture None JP.GM POLYGON ((139.50237 36.18904, 139.49628 36.188... 10
10 JPN Japan JPN.11_1 Hiroshima Hirosima 広島県 Ken Prefecture None JP.HS MULTIPOLYGON (((132.48372 34.03422, 132.48318 ... 34
11 JPN Japan JPN.12_1 Hokkaido Ezo|Yeso|Yezo 北海道 Do Circuit None JP.HK MULTIPOLYGON (((140.09169 41.41886, 140.09129 ... 1
12 JPN Japan JPN.13_1 Hyōgo Hiogo 兵庫県 Ken Prefecture None JP.HG MULTIPOLYGON (((134.82297 34.17979, 134.82336 ... 28
13 JPN Japan JPN.14_1 Ibaraki None 茨城県 Ken Prefecture None JP.IB MULTIPOLYGON (((140.69528 35.92944, 140.69444 ... 8
14 JPN Japan JPN.15_1 Ishikawa Isikawa 石川県 Ken Prefecture None JP.IS MULTIPOLYGON (((136.90479 37.40308, 136.90524 ... 17
15 JPN Japan JPN.16_1 Iwate None 岩手県 Ken Prefecture None JP.IW MULTIPOLYGON (((141.72762 39.03545, 141.72708 ... 3
16 JPN Japan JPN.17_1 Kagawa None 香川県 Ken Prefecture None JP.KG MULTIPOLYGON (((133.53694 34.12017, 133.53493 ... 37
17 JPN Japan JPN.18_1 Kagoshima None 鹿児島県 Ken Prefecture None JP.KS MULTIPOLYGON (((128.43361 27.06861, 128.43388 ... 46
18 JPN Japan JPN.19_1 Kanagawa None 神奈川県 Ken Prefecture None JP.KN MULTIPOLYGON (((139.61588 35.13718, 139.61618 ... 14
19 JPN Japan JPN.20_1 Kochi Koti 高知県 Ken Prefecture None JP.KC MULTIPOLYGON (((132.48972 32.74389, 132.49028 ... 39
20 JPN Japan JPN.21_1 Kumamoto None 熊本県 Ken Prefecture None JP.KM MULTIPOLYGON (((130.15723 32.08556, 130.15695 ... 43
21 JPN Japan JPN.22_1 Kyoto Kioto 京都府 Fu Urban Prefecture None JP.KY POLYGON ((136.02983 34.81502, 136.01799 34.805... 26
22 JPN Japan JPN.23_1 Mie Miye 三重県 Ken Prefecture None JP.ME MULTIPOLYGON (((136.29361 34.08222, 136.29361 ... 24
23 JPN Japan JPN.24_1 Miyagi None 宮城県 Ken Prefecture None JP.MG MULTIPOLYGON (((140.90611 38.03583, 140.90639 ... 4
24 JPN Japan JPN.25_1 Miyazaki None 宮崎県 Ken Prefecture None JP.MZ MULTIPOLYGON (((131.41295 31.54124, 131.41327 ... 45
25 JPN Japan JPN.26_1 Nagano None 長野県 Ken Prefecture None JP.NN POLYGON ((137.65213 35.21122, 137.64482 35.205... 20
26 JPN Japan JPN.27_1 Naoasaki Nagasaki 長崎県 Ken Prefecture None JP.NS MULTIPOLYGON (((128.35547 32.00866, 128.35594 ... 42
27 JPN Japan JPN.28_1 Nara None 奈良県 Ken Prefecture None JP.NR POLYGON ((135.86241 33.89688, 135.84920 33.893... 29
28 JPN Japan JPN.29_1 Niigata None 新潟県 Ken Prefecture None JP.NI MULTIPOLYGON (((138.33722 38.20028, 138.33640 ... 15
29 JPN Japan JPN.30_1 Oita None 大分県 Ken Prefecture None JP.OT MULTIPOLYGON (((131.92316 32.72695, 131.92377 ... 44
30 JPN Japan JPN.31_1 Okayama None 岡山県 Ken Prefecture None JP.OY MULTIPOLYGON (((133.54041 34.30756, 133.53979 ... 33
31 JPN Japan JPN.32_1 Okinawa None 沖縄県 Ken Prefecture None JP.ON MULTIPOLYGON (((123.78792 24.07208, 123.78792 ... 47
32 JPN Japan JPN.33_1 Osaka None 大阪府 Fu Urban Prefecture None JP.OS MULTIPOLYGON (((135.31573 34.43310, 135.31544 ... 27
33 JPN Japan JPN.34_1 Saga None 佐賀県 Ken Prefecture None JP.SG MULTIPOLYGON (((129.77444 33.49556, 129.77499 ... 41
34 JPN Japan JPN.35_1 Saitama None 埼玉県 Ken Prefecture None JP.ST POLYGON ((139.84909 35.79491, 139.84793 35.795... 11
35 JPN Japan JPN.36_1 Shiga Siga 滋賀県 Ken Prefecture None JP.SH POLYGON ((136.28865 34.86865, 136.27882 34.869... 25
36 JPN Japan JPN.37_1 Shimane Simane 島根県 Ken Prefecture None JP.SM MULTIPOLYGON (((131.83215 34.83653, 131.83249 ... 32
37 JPN Japan JPN.38_1 Shizuoka Sizuoka 静岡県 Ken Prefecture None JP.SZ MULTIPOLYGON (((141.46085 24.24579, 141.46115 ... 22
38 JPN Japan JPN.39_1 Tochigi Totigi 栃木県 Ken Prefecture None JP.TC POLYGON ((139.49724 36.27460, 139.48871 36.272... 9
39 JPN Japan JPN.40_1 Tokushima Tokusima 徳島県 Ken Prefecture None JP.TS MULTIPOLYGON (((134.36798 33.58724, 134.36761 ... 36
40 JPN Japan JPN.41_1 Tokyo Edo|Yedo|Tokio|T¢quio 東京都 To Metropolis None JP.TK MULTIPOLYGON (((139.74005 35.54153, 139.74028 ... 13
41 JPN Japan JPN.42_1 Tottori None 鳥取県 Ken Prefecture None JP.TT MULTIPOLYGON (((134.22307 35.19029, 134.21843 ... 31
42 JPN Japan JPN.43_1 Toyama None 富山県 Ken Prefecture None JP.TY POLYGON ((136.78896 36.33339, 136.79283 36.341... 16
43 JPN Japan JPN.44_1 Wakayama None 和歌山県 Ken Prefecture None JP.WK MULTIPOLYGON (((135.82077 33.45090, 135.82062 ... 30
44 JPN Japan JPN.45_1 Yamagata None 山形県 Ken Prefecture None JP.YT MULTIPOLYGON (((139.68417 38.72306, 139.68333 ... 6
45 JPN Japan JPN.46_1 Yamaguchi Yamaguti 山口県 Ken Prefecture None JP.YC MULTIPOLYGON (((132.48804 33.73760, 132.48842 ... 35
46 JPN Japan JPN.47_1 Yamanashi Yamanasi 山梨県 Ken Prefecture None JP.YN POLYGON ((138.52417 35.19426, 138.52386 35.193... 19
試しに、プロットしてみます
>>> df_jpn.plot()
<AxesSubplot:>
>>> plt.show()
これで地形を表示することができるようになりました。
つづいてワクチンの摂取数データに移ります。
ワクチン接種数データを用意しよう!
政府CIOポータルの新型コロナワクチンの接種状況に関するオープンデータ仕様を見てダウンロードします。
$ curl https://vrs-data.cio.go.jp/vaccination/opendata/latest/prefecture.ndjson -o prefecture.ndjson.gz
$ gunzip prefecture.ndjson.gz
$ head -n 5 prefecture.ndjson
{"date":"2021-04-12","prefecture":"01","gender":"F","age":"-64","medical_worker":false,"status":1,"count":117}
{"date":"2021-04-12","prefecture":"01","gender":"F","age":"65-","medical_worker":false,"status":1,"count":88}
{"date":"2021-04-12","prefecture":"01","gender":"M","age":"-64","medical_worker":false,"status":1,"count":34}
{"date":"2021-04-12","prefecture":"01","gender":"M","age":"65-","medical_worker":false,"status":1,"count":25}
{"date":"2021-04-12","prefecture":"01","gender":"U","age":"-64","medical_worker":false,"status":1,"count":12}
何も考えずread_csvしてみます。
>>> df_vaccine = pd.read_csv('prefecture.ndjson')
>>> df_vaccine
{"date":"2021-04-12" prefecture:"01" gender:"F" age:"-64" medical_worker:false status:1 count:117}
0 {"date":"2021-04-12" prefecture:"01" gender:"F" age:"65-" medical_worker:false status:1 count:88}
1 {"date":"2021-04-12" prefecture:"01" gender:"M" age:"-64" medical_worker:false status:1 count:34}
2 {"date":"2021-04-12" prefecture:"01" gender:"M" age:"65-" medical_worker:false status:1 count:25}
3 {"date":"2021-04-12" prefecture:"01" gender:"U" age:"-64" medical_worker:false status:1 count:12}
4 {"date":"2021-04-12" prefecture:"01" gender:"U" age:"UNK" medical_worker:false status:1 count:1}
... ... ... ... ... ... ... ...
23106 {"date":"2021-06-16" prefecture:"47" gender:"M" age:"-64" medical_worker:false status:2 count:70}
23107 {"date":"2021-06-16" prefecture:"47" gender:"M" age:"65-" medical_worker:false status:1 count:1558}
23108 {"date":"2021-06-16" prefecture:"47" gender:"M" age:"65-" medical_worker:false status:2 count:1132}
23109 {"date":"2021-06-16" prefecture:"47" gender:"U" age:"UNK" medical_worker:false status:1 count:35}
23110 {"date":"2021-06-16" prefecture:"47" gender:"U" age:"UNK" medical_worker:false status:2 count:3}
[23111 rows x 7 columns]
なんかそれぞれの行がまるごとjsonのままになってます。
ndjsonっていうのは、複数のjsonを改行でつないだデータのようです。
このままだと扱いづらいので、lines=Trueにして再度読み込んでみます。
>>> df_vaccine = pd.read_json('prefecture.ndjson', lines=True)
>>> df_vaccine
date prefecture gender age medical_worker status count
0 2021-04-12 1 F -64 False 1 117
1 2021-04-12 1 F 65- False 1 88
2 2021-04-12 1 M -64 False 1 34
3 2021-04-12 1 M 65- False 1 25
4 2021-04-12 1 U -64 False 1 12
... ... ... ... ... ... ... ...
23107 2021-06-16 47 M -64 False 2 70
23108 2021-06-16 47 M 65- False 1 1558
23109 2021-06-16 47 M 65- False 2 1132
23110 2021-06-16 47 U UNK False 1 35
23111 2021-06-16 47 U UNK False 2 3
[23112 rows x 7 columns]
おー、みれたみれた、この中で(今回作るもので)重要なのは、date, prefecture, status, countです。dateが日付、prefectureが都道府県コード、statusが1回目接種完了か、2回目接種完了か、countが接種数です。
prefectureが都道府県コードなので、このままでもいいんですが、もしかしたら都道府県名で突き合わせる可能性もなくもないので、一応都道府県名を入れておきます。
>>> df_vaccine['都道府県'] = df_vaccine.prefecture.map(lambda x: '{:02d}_{:s}'.format(x, pref_code2name[x]))
>>> df_vaccine['都道府県名'] = df_vaccine.prefecture.map(lambda x: pref_code2name[x])
>>> df_vaccine
date prefecture gender age medical_worker status count 都道府県 都道府県名
0 2021-04-12 1 F -64 False 1 117 01_北海道 北海道
1 2021-04-12 1 F 65- False 1 88 01_北海道 北海道
2 2021-04-12 1 M -64 False 1 34 01_北海道 北海道
3 2021-04-12 1 M 65- False 1 25 01_北海道 北海道
4 2021-04-12 1 U -64 False 1 12 01_北海道 北海道
... ... ... ... ... ... ... ... ... ...
23107 2021-06-16 47 M -64 False 2 70 47_沖縄県 沖縄県
23108 2021-06-16 47 M 65- False 1 1558 47_沖縄県 沖縄県
23109 2021-06-16 47 M 65- False 2 1132 47_沖縄県 沖縄県
23110 2021-06-16 47 U UNK False 1 35 47_沖縄県 沖縄県
23111 2021-06-16 47 U UNK False 2 3 47_沖縄県 沖縄県
[23112 rows x 9 columns]
試しに、東京都で2回目の接種を終えた人の、日付ごと(推移)のデータを見てみます。
>>> df_vaccine[(df_vaccine['都道府県名'] == '東京都') & (df_vaccine['status'] == 2)].groupby('date')['count'].sum()
date
2021-05-05 2
2021-05-06 71
2021-05-07 112
2021-05-08 223
2021-05-09 5
2021-05-10 642
2021-05-11 375
2021-05-12 712
2021-05-13 1100
2021-05-14 1110
2021-05-15 733
2021-05-16 669
2021-05-17 959
2021-05-18 736
2021-05-19 1029
2021-05-20 391
2021-05-21 620
2021-05-22 485
2021-05-23 293
2021-05-24 616
2021-05-25 443
2021-05-26 718
2021-05-27 1890
2021-05-28 1109
2021-05-29 1255
2021-05-30 7322
2021-05-31 4409
2021-06-01 5333
2021-06-02 8808
2021-06-03 9375
2021-06-04 7309
2021-06-05 11370
2021-06-06 23378
2021-06-07 10135
2021-06-08 13397
2021-06-09 19723
2021-06-10 20000
2021-06-11 14571
2021-06-12 20926
2021-06-13 34965
2021-06-14 21699
2021-06-15 24250
2021-06-16 21289
Name: count, dtype: int64
ついでにグラフも見てみます。
>>> import matplotlib.pyplot as plt
>>> df_vaccine[(df_vaccine['都道府県名'] == '東京都') & (df_vaccine['status'] == 2)].groupby('date')['count'].sum().plot()
>>> plt.show()
ということで、無事ワクチンの摂取数データは読み込めたようです。
次は、人口のデータを取得していきます。
人口データを用意しよう!
e-statに国勢調査の結果として都道府県人口がまとめられたcsvファイルがあったのでこれをダウンロードしてみます。
$ curl "https://www.e-stat.go.jp/stat-search/file-download?statInfId=000031524010&fileKind=1" -o population.csv
$ head -n 5 population.csv
"s{R[h","s{","","aiNj","iNj","","lij","lijj","lij"
"00","S","吳",9,1920,"",55963053,28044185,27918868
"01","kC","吳",9,1920,"",2359183,1244322,1114861
"02","X"," ",9,1920,"",756454,381293,375161
"03","","吳",9,1920,"",845540,421069,424471
とりあえず読み込んでみます。
>>> df_population = pd.read_csv('population.csv')
>>> df_population
�s���{���R�[�h �s���{���� ���� �a��i�N�j ����i�N�j �� �l���i�����j �l���i�j�j �l���i���j
0 00 �S�� �吳 9.0 1920.0 NaN 55963053 28044185 27918868
1 01 �k�C�� �吳 9.0 1920.0 NaN 2359183 1244322 1114861
2 02 �X�� � 9.0 1920.0 NaN 756454 381293 375161
3 03 ��茧 �吳 9.0 1920.0 NaN 845540 421069 424471
4 04 �{�錧 �吳 9.0 1920.0 NaN 961768 485309 476459
.. ... ... ... ... ... ... ... ... ...
977 45 �{�茧 ���� 27.0 2015.0 NaN 1104069 519242 584827
978 46 �������� ���� 27.0 2015.0 NaN 1648177 773061 875116
979 47 ���ꌧ ���� 27.0 2015.0 NaN 1433566 704619 728947
980 1)�@���ꌧ�͒�������Ȃ��������߁C�܂܂�Ă��Ȃ��B NaN NaN NaN NaN NaN NaN NaN NaN
981 2)�@���쌧���}���Q�R�����Ɗ����Ð�s�̋��E�����n��l... NaN NaN NaN NaN NaN NaN NaN NaN
[982 rows x 9 columns]
ハチャメチャ文字化けしました。
だいたいこういう役所のサイトはsjisのパターンなので、sjisにして読み込んでみます。(大学のセンセイのサイトで文字化けしたときはだいたいeucjpの事が多い)
>>> df_population = pd.read_csv('population.csv', encoding='sjis')
>>> df_population
都道府県コード 都道府県名 元号 和暦(年) 西暦(年) 注 人口(総数) 人口(男) 人口(女)
0 00 全国 大正 9.0 1920.0 NaN 55963053 28044185 27918868
1 01 北海道 大正 9.0 1920.0 NaN 2359183 1244322 1114861
2 02 青森県 大正 9.0 1920.0 NaN 756454 381293 375161
3 03 岩手県 大正 9.0 1920.0 NaN 845540 421069 424471
4 04 宮城県 大正 9.0 1920.0 NaN 961768 485309 476459
.. ... ... ... ... ... ... ... ... ...
977 45 宮崎県 平成 27.0 2015.0 NaN 1104069 519242 584827
978 46 鹿児島県 平成 27.0 2015.0 NaN 1648177 773061 875116
979 47 沖縄県 平成 27.0 2015.0 NaN 1433566 704619 728947
980 1) 沖縄県は調査されなかったため,含まれていない。 NaN NaN NaN NaN NaN NaN NaN NaN
981 2) 長野県西筑摩群山口村と岐阜県中津川市の境界紛争地域人口(男39人,女34人)は全国に含... NaN NaN NaN NaN NaN NaN NaN NaN
[982 rows x 9 columns]
読み込めました。
ちなみに、ちゃんと知りたかったら、nkfで調べましょう。
$ nkf --guess population.csv
Shift_JIS (CRLF)
最後2行の注釈が邪魔なので消します。
>>> df_population = df_population[:-2]
>>> df_population
都道府県コード 都道府県名 元号 和暦(年) 西暦(年) 注 人口(総数) 人口(男) 人口(女)
0 00 全国 大正 9.0 1920.0 NaN 55963053 28044185 27918868
1 01 北海道 大正 9.0 1920.0 NaN 2359183 1244322 1114861
2 02 青森県 大正 9.0 1920.0 NaN 756454 381293 375161
3 03 岩手県 大正 9.0 1920.0 NaN 845540 421069 424471
4 04 宮城県 大正 9.0 1920.0 NaN 961768 485309 476459
.. ... ... .. ... ... ... ... ... ...
975 43 熊本県 平成 27.0 2015.0 NaN 1786170 841046 945124
976 44 大分県 平成 27.0 2015.0 NaN 1166338 551932 614406
977 45 宮崎県 平成 27.0 2015.0 NaN 1104069 519242 584827
978 46 鹿児島県 平成 27.0 2015.0 NaN 1648177 773061 875116
979 47 沖縄県 平成 27.0 2015.0 NaN 1433566 704619 728947
[980 rows x 9 columns]
きえました。どうやらこのデータは過去の国勢調査の結果も載っているようです。
たしかに、ダウンロードしたサイトには推移csvとかかれていました。
ここに乗っている最新の国勢調査2015年のものを抜き取ります。
>>> df_population = df_population[df_population["西暦(年)"] == 2015]
>>> df_population
都道府県コード 都道府県名 元号 和暦(年) 西暦(年) 注 人口(総数) 人口(男) 人口(女)
930 00 全国 平成 27.0 2015.0 NaN 127094745 61841738 65253007
931 0A 人口集中地区 平成 27.0 2015.0 NaN 86868176 42363423 44504753
932 0B 人口集中地区以外の地区 平成 27.0 2015.0 NaN 40226569 19478315 20748254
933 01 北海道 平成 27.0 2015.0 NaN 5381733 2537089 2844644
934 02 青森県 平成 27.0 2015.0 NaN 1308265 614694 693571
935 03 岩手県 平成 27.0 2015.0 NaN 1279594 615584 664010
936 04 宮城県 平成 27.0 2015.0 NaN 2333899 1140167 1193732
937 05 秋田県 平成 27.0 2015.0 NaN 1023119 480336 542783
938 06 山形県 平成 27.0 2015.0 NaN 1123891 540226 583665
939 07 福島県 平成 27.0 2015.0 NaN 1914039 945660 968379
940 08 茨城県 平成 27.0 2015.0 NaN 2916976 1453594 1463382
941 09 栃木県 平成 27.0 2015.0 NaN 1974255 981626 992629
942 10 群馬県 平成 27.0 2015.0 NaN 1973115 973283 999832
943 11 埼玉県 平成 27.0 2015.0 NaN 7266534 3628418 3638116
944 12 千葉県 平成 27.0 2015.0 NaN 6222666 3095860 3126806
945 13 東京都 平成 27.0 2015.0 NaN 13515271 6666690 6848581
946 14 神奈川県 平成 27.0 2015.0 NaN 9126214 4558978 4567236
947 15 新潟県 平成 27.0 2015.0 NaN 2304264 1115413 1188851
948 16 富山県 平成 27.0 2015.0 NaN 1066328 515147 551181
949 17 石川県 平成 27.0 2015.0 NaN 1154008 558589 595419
950 18 福井県 平成 27.0 2015.0 NaN 786740 381474 405266
951 19 山梨県 平成 27.0 2015.0 NaN 834930 408327 426603
952 20 長野県 平成 27.0 2015.0 NaN 2098804 1022129 1076675
953 21 岐阜県 平成 27.0 2015.0 NaN 2031903 983850 1048053
954 22 静岡県 平成 27.0 2015.0 NaN 3700305 1820993 1879312
955 23 愛知県 平成 27.0 2015.0 NaN 7483128 3740844 3742284
956 24 三重県 平成 27.0 2015.0 NaN 1815865 883516 932349
957 25 滋賀県 平成 27.0 2015.0 NaN 1412916 696941 715975
958 26 京都府 平成 27.0 2015.0 NaN 2610353 1248972 1361381
959 27 大阪府 平成 27.0 2015.0 NaN 8839469 4256049 4583420
960 28 兵庫県 平成 27.0 2015.0 NaN 5534800 2641561 2893239
961 29 奈良県 平成 27.0 2015.0 NaN 1364316 643946 720370
962 30 和歌山県 平成 27.0 2015.0 NaN 963579 453216 510363
963 31 鳥取県 平成 27.0 2015.0 NaN 573441 273705 299736
964 32 島根県 平成 27.0 2015.0 NaN 694352 333112 361240
965 33 岡山県 平成 27.0 2015.0 NaN 1921525 922226 999299
966 34 広島県 平成 27.0 2015.0 NaN 2843990 1376211 1467779
967 35 山口県 平成 27.0 2015.0 NaN 1404729 665008 739721
968 36 徳島県 平成 27.0 2015.0 NaN 755733 359790 395943
969 37 香川県 平成 27.0 2015.0 NaN 976263 472308 503955
970 38 愛媛県 平成 27.0 2015.0 NaN 1385262 654380 730882
971 39 高知県 平成 27.0 2015.0 NaN 728276 342672 385604
972 40 福岡県 平成 27.0 2015.0 NaN 5101556 2410418 2691138
973 41 佐賀県 平成 27.0 2015.0 NaN 832832 393073 439759
974 42 長崎県 平成 27.0 2015.0 NaN 1377187 645763 731424
975 43 熊本県 平成 27.0 2015.0 NaN 1786170 841046 945124
976 44 大分県 平成 27.0 2015.0 NaN 1166338 551932 614406
977 45 宮崎県 平成 27.0 2015.0 NaN 1104069 519242 584827
978 46 鹿児島県 平成 27.0 2015.0 NaN 1648177 773061 875116
979 47 沖縄県 平成 27.0 2015.0 NaN 1433566 704619 728947
上の三行は全国とかの集計データぽいので落とします。
>>> df = df[3:]
>>> df
都道府県コード 都道府県名 元号 和暦(年) 西暦(年) 注 人口(総数) 人口(男) 人口(女)
933 01 北海道 平成 27.0 2015.0 NaN 5381733 2537089 2844644
934 02 青森県 平成 27.0 2015.0 NaN 1308265 614694 693571
935 03 岩手県 平成 27.0 2015.0 NaN 1279594 615584 664010
936 04 宮城県 平成 27.0 2015.0 NaN 2333899 1140167 1193732
937 05 秋田県 平成 27.0 2015.0 NaN 1023119 480336 542783
938 06 山形県 平成 27.0 2015.0 NaN 1123891 540226 583665
939 07 福島県 平成 27.0 2015.0 NaN 1914039 945660 968379
940 08 茨城県 平成 27.0 2015.0 NaN 2916976 1453594 1463382
941 09 栃木県 平成 27.0 2015.0 NaN 1974255 981626 992629
942 10 群馬県 平成 27.0 2015.0 NaN 1973115 973283 999832
943 11 埼玉県 平成 27.0 2015.0 NaN 7266534 3628418 3638116
944 12 千葉県 平成 27.0 2015.0 NaN 6222666 3095860 3126806
945 13 東京都 平成 27.0 2015.0 NaN 13515271 6666690 6848581
946 14 神奈川県 平成 27.0 2015.0 NaN 9126214 4558978 4567236
947 15 新潟県 平成 27.0 2015.0 NaN 2304264 1115413 1188851
948 16 富山県 平成 27.0 2015.0 NaN 1066328 515147 551181
949 17 石川県 平成 27.0 2015.0 NaN 1154008 558589 595419
950 18 福井県 平成 27.0 2015.0 NaN 786740 381474 405266
951 19 山梨県 平成 27.0 2015.0 NaN 834930 408327 426603
952 20 長野県 平成 27.0 2015.0 NaN 2098804 1022129 1076675
953 21 岐阜県 平成 27.0 2015.0 NaN 2031903 983850 1048053
954 22 静岡県 平成 27.0 2015.0 NaN 3700305 1820993 1879312
955 23 愛知県 平成 27.0 2015.0 NaN 7483128 3740844 3742284
956 24 三重県 平成 27.0 2015.0 NaN 1815865 883516 932349
957 25 滋賀県 平成 27.0 2015.0 NaN 1412916 696941 715975
958 26 京都府 平成 27.0 2015.0 NaN 2610353 1248972 1361381
959 27 大阪府 平成 27.0 2015.0 NaN 8839469 4256049 4583420
960 28 兵庫県 平成 27.0 2015.0 NaN 5534800 2641561 2893239
961 29 奈良県 平成 27.0 2015.0 NaN 1364316 643946 720370
962 30 和歌山県 平成 27.0 2015.0 NaN 963579 453216 510363
963 31 鳥取県 平成 27.0 2015.0 NaN 573441 273705 299736
964 32 島根県 平成 27.0 2015.0 NaN 694352 333112 361240
965 33 岡山県 平成 27.0 2015.0 NaN 1921525 922226 999299
966 34 広島県 平成 27.0 2015.0 NaN 2843990 1376211 1467779
967 35 山口県 平成 27.0 2015.0 NaN 1404729 665008 739721
968 36 徳島県 平成 27.0 2015.0 NaN 755733 359790 395943
969 37 香川県 平成 27.0 2015.0 NaN 976263 472308 503955
970 38 愛媛県 平成 27.0 2015.0 NaN 1385262 654380 730882
971 39 高知県 平成 27.0 2015.0 NaN 728276 342672 385604
972 40 福岡県 平成 27.0 2015.0 NaN 5101556 2410418 2691138
973 41 佐賀県 平成 27.0 2015.0 NaN 832832 393073 439759
974 42 長崎県 平成 27.0 2015.0 NaN 1377187 645763 731424
975 43 熊本県 平成 27.0 2015.0 NaN 1786170 841046 945124
976 44 大分県 平成 27.0 2015.0 NaN 1166338 551932 614406
977 45 宮崎県 平成 27.0 2015.0 NaN 1104069 519242 584827
978 46 鹿児島県 平成 27.0 2015.0 NaN 1648177 773061 875116
979 47 沖縄県 平成 27.0 2015.0 NaN 1433566 704619 728947
なんかいい感じになったので、いらない列もなんとなく落としときます。
あと、数値じゃなくて文字列として認識されてしまっているようなので、それも変換しときます。
>>> df_population = df.drop(columns=['元号', '和暦(年)', '西暦(年)', '注'])
>>> df_population = df_population.astype({'都道府県コード': int, '人口(総数)': int, '人口(男)': int, '人口(女)': int})
>>> df_population
都道府県コード 都道府県名 人口(総数) 人口(男) 人口(女)
933 1 北海道 5381733 2537089 2844644
934 2 青森県 1308265 614694 693571
935 3 岩手県 1279594 615584 664010
936 4 宮城県 2333899 1140167 1193732
937 5 秋田県 1023119 480336 542783
938 6 山形県 1123891 540226 583665
939 7 福島県 1914039 945660 968379
940 8 茨城県 2916976 1453594 1463382
941 9 栃木県 1974255 981626 992629
942 10 群馬県 1973115 973283 999832
943 11 埼玉県 7266534 3628418 3638116
943 11 埼玉県 7266534 3628418 3638116
944 12 千葉県 6222666 3095860 3126806
945 13 東京都 13515271 6666690 6848581
946 14 神奈川県 9126214 4558978 4567236
947 15 新潟県 2304264 1115413 1188851
948 16 富山県 1066328 515147 551181
949 17 石川県 1154008 558589 595419
950 18 福井県 786740 381474 405266
951 19 山梨県 834930 408327 426603
952 20 長野県 2098804 1022129 1076675
953 21 岐阜県 2031903 983850 1048053
954 22 静岡県 3700305 1820993 1879312
955 23 愛知県 7483128 3740844 3742284
956 24 三重県 1815865 883516 932349
957 25 滋賀県 1412916 696941 715975
958 26 京都府 2610353 1248972 1361381
959 27 大阪府 8839469 4256049 4583420
960 28 兵庫県 5534800 2641561 2893239
961 29 奈良県 1364316 643946 720370
962 30 和歌山県 963579 453216 510363
963 31 鳥取県 573441 273705 299736
964 32 島根県 694352 333112 361240
965 33 岡山県 1921525 922226 999299
966 34 広島県 2843990 1376211 1467779
967 35 山口県 1404729 665008 739721
968 36 徳島県 755733 359790 395943
969 37 香川県 976263 472308 503955
970 38 愛媛県 1385262 654380 730882
971 39 高知県 728276 342672 385604
972 40 福岡県 5101556 2410418 2691138
973 41 佐賀県 832832 393073 439759
974 42 長崎県 1377187 645763 731424
975 43 熊本県 1786170 841046 945124
976 44 大分県 1166338 551932 614406
977 45 宮崎県 1104069 519242 584827
978 46 鹿児島県 1648177 773061 875116
979 47 沖縄県 1433566 704619 728947
いい感じに2015年時点での各都道府県の人口を取得できました。
さいごにこれまで集めてきたデータを合体させてプロットさせます。
合体だ!
まず、ワクチン接種数データから、表示したいデータの条件で、抽出・集計をします。
この例では、ワクチン接種1回目の各都道府県の接種回数を取っています。
>>> df_vaccine_result = df_vaccine[df_vaccine.status == 1].groupby('prefecture')['count'].sum().fillna(0)
これを地形データといい感じに、合体させます。
ここで都道府県コードが役に立ちます。
>>> df = df_jpn.merge(df_vaccine_result, left_on='都道府県コード', right_on='prefecture', how='left')
似たような感じで、人口データと合体させます。
摂取回数ではなくて、本当は接種率を出したいので、人口が必要なのです。
>>> df = df.merge(df_population, left_on='都道府県コード', right_on='都道府県コード', how='left')
接種率を計算します。
摂取回数を人口で割るだけです。
ワクチン接種数データからの集計方法によっては、都道府県単位で集計したときに該当するデータがなくて、nanになってしまうので、一応0梅しときます。
df['count'] = df['count'].fillna(0)
df['接種率'] = df['count'] / df['人口(総数)'] * 100
で、あとはplotするだけ、geopythonなのでめっちゃかんたん!
>>> df.plot(ax=ax, column='接種率', vmin=0.0, vmax=20, cmap='rainbow', edgecolors='black', legend=True)
うぉー、かんたんだーすげー。
あとは、maplotlibのマニュアルとにらめっこしながら、テキストを追加したり、
接種数の抽出条件をいじって、日付単位で出したり、
それloopでpngに書き出して、
いい感じにffmpegすると、
あれができます。
コード全体はあとでgithubにあげようと思います。
変なところあったら、twitterリプライかqiitaのコメント下さい。