Python の folium パッケージを使用した色分け地図の作成方法を紹介します。
ライブラリの使い方やデータの作成方法などをソースコードも添えて説明をします。
感染症の定点当たりの患者数の色分け地図を題材にしています。
新型コロナとインフルエンザの患者数の違いを地図で比較できます。
▽アプリの結果の HTML ブラウザ出力と画面
目次
- ◆地図のみの表示
- ◆都道府県で区分けした地図の表示(GeoJSON使用)
- ◆都道府県で区分けした地図の表示(TopoJSON使用)
- ◆色分け地図の表示(TopoJSON使用)
- ◆定点把握疾患の定点あたりの報告数をwebから取得
- ◆地図を2つ並べて表示
- ◆アプリとしての作り込み
- ◆GeoJSONとTopoJSON
- ◆foliumパッケージ
- ◆Tkinterの使い方
- ◆tkcalendarパッケージ
- ◆ソースの取得
- ◆さいごに
- ◆参考
◆地図のみの表示
見るためには、もう1命令でブラウザに表示します。
地図作成時、最低限、地図の位置と大きさを指定します。
◇手順
- 地図の作成:Map インスタンスを作成
・・・Map コンストラクタの説明は⤵ - 地図の表示:Map オブジェクトの
show_in_browser()
メソッドでブラウザに表示
◇コード:地図表示
import folium map = folium.Map(location=[35.69, 139.70] , zoom_start=10) map.show_in_browser()
◆都道府県で区分けした地図の表示(GeoJSON使用)
folium では、マップタイルセットを変更することで、いろいろな見た目の地図を作成することができます。
マップタイルセットに白地図のような「Cartodb Positron」を使って都道府県の境界を分かりやすくします。
都道府県の境界用のデータに GeoJSON 型式のデータを使用します。・・・GeoJson データの取得方法は⤵
地図を作成し、都道府県の境界線を作成し、それらを重ねるイメージです。
◇手順(GeoJSON使用)
- 地図の作成:Map インスタンスを作成
- 境界線の作成:GeoJson データを指定して GeoJson インスタンスを作成、Map オブジェクトに追加
・・・GeoJson コンストラクタの説明は⤵ - 地図の表示:Map オブジェクトの
show_in_browser()
メソッドでブラウザに表示
◇コード:都道府県で区分けしたの表示(GeoJSON使用)
import folium def basic_map_geo(): # 単純な地図の表示 map = folium.Map(location=[35.69, 139.70] , zoom_start=10 , tiles='Cartodb Positron') # GeoJSON の利用 _url = "https://raw.githubusercontent.com/smartnews-smri/japan-topography/main/data/municipality/geojson/s0010/prefectures.json" # 全国都道府県 folium.GeoJson(_url).add_to(map) map.show_in_browser() basic_map_geo()
◆都道府県で区分けした地図の表示(TopoJSON使用)
folium では、マップタイルセットを変更することで、いろいろな見た目の地図を作成することができます。
マップタイルセットに白地図のような「Cartodb Positron」を使って都道府県の境界を分かりやすくします。
都道府県の境界用のデータに TopoJSON 型式のデータを使用します。・・・TopoJSON データの取得方法は⤵
GeoJSON のネット上のデータは GeoJson コンストラクタで直接読めますが、TopoJSON のネット上のデータは TopoJson コンストラクタで直接読めないので requets.get()
メソッドで先に読みます。
また、TopoJSON コンストラクタでは、TopoJSON データ内の geometries を求めるパスを指定します。・・・TopoJson コンストラクタの説明は⤵
全体としては、GeoJSON を使用した時と同様に、地図を作成し、都道府県の境界線を作成し、それらを重ねるイメージです。
出力結果は、GeoJSON を使った時と同じです。
◇手順(TopoJSON使用)
- 地図の作成:Map インスタンスを作成
- 境界線データの読み込み:
requests.get()
メソッドで TopoJSON データの読み込み - 境界線の作成:TopoJson データを指定して TopoJson インスタンスを作成、Map オブジェクトに追加
- 地図の表示:Map オブジェクトの
show_in_browser()
メソッドで表示
◇コード:都道府県で区分けした地図の表示(TopoJSON使用)
import folium import requests def basic_map_topo(): # 単純な地図の表示 map = folium.Map(location=[35.69, 139.70] , zoom_start=10 , tiles='Cartodb Positron') # TopoJSON の利用 _url = "https://raw.githubusercontent.com/smartnews-smri/japan-topography/main/data/municipality/topojson/s0010/prefectures.json" # 全国都道府県 topo_json_data = requests.get(_url).json() folium.TopoJson(topo_json_data , "objects.prefectures").add_to(map) map.show_in_browser() basic_map_topo()
◆色分け地図の表示(TopoJSON使用)
色分け地図は、folium の Choropleth オブジェクトを作成し、Map オブジェクトに追加して作成します。
Choropleth オブジェクトを作成する際に、色分け用のデータを用意する必要があります。・・・データの作り方は ⤵
Choropleth コンストラクタでは、必要に応じ、色分け用の色の指定などが可能です。・・・Choropleth コンストラクタの説明は⤵
◇色分け用のデータをTopoJSONに指定
色分け用のデータをChoropleth コンストラクタで使用するには、DateFrame 型、Series 型、または辞書に変換可能なデータである必要があります。
Pandas を使えば、データの取得が簡単で、かつ DataFrame 型のデータができるので扱いやすいのですが、ここでは、辞書に変換可能なデータを用意しました。
辞書に変換可能なデータとして、キーと値のタプルのリストを用意します。
例:[('key1',1), ('key2', 2), ('key3', 3)]
この時、キーは TopoJSON データでキーとして使用しているデータ(今回は都道府県名)にあわせます。
これを、Choropleth コンストラクタの data
引数に指定し、さらに、key_on
引数で GeoJSON(TopoJSON) データのどの要素とマッチングさせるかを指定します。
◇ツールチップの表示
色分けした根拠となる数字を見せる対応方法として、ツールチップがあります。
ツールチップを表示するためには、色分け用のデータを TopoJSON データにも追加する必要があります。
追加位置は、TopoJSON データの objects オブジェクトの中です。objects オブジェクトは階層構造になっており、その子孫は次の通りです。
objects
→prefectures
→geometries
→properties
geometries が配列で都道府県ごとにあり、色分け用のデータは、properties オブジェクトに追加します。
properties オブジェクトには、既にキーN03_001
、値が都道府県名の要素が存在します。
そこに都道府県名が一致するように色分け用データを追加します。・・・データの構造は⤵
ツールチップは、GeoJsonTooltip コンストラクタで作成します。・・・GeoJsonTooltip コンストラクタの説明は⤵
今回作成するツールチップは次のように出力します。
地域 ○○県 人数 12.34
◇手順
- 地図の作成:Map インスタンスを作成
- 境界線データの読み込み:
requests.get()
メソッドで TopoJSON データを読み込み - 境界線の作成:TopoJson データを指定し TopoJson インスタンスを作成、Map オブジェクトに追加
- 地図の色分け:Choropleth インスタンスを作成し、Map オブジェクトに追加
geo_date
引数で TopoJSON データを指定topojson
引数で TopoJSON データ内の geometries オブジェクトの位置を指定data
引数で色分けするデータを指定key_on
引数で data で指定した値を特定する TopoJSON データ内のキーを指定
- ツールチップの作成
- 地図の表示:Map オブジェクトの
show_in_browser()
メソッドで表示
◇コード:色分け地図の表示
import folium import requests def Choropleth_map_topo(rows, max_value): """ 階級区分図の作成(TopoJSONを使用) Args: list: 報告数データ(都道府県と報告数のタプルのリスト) int: 報告数の最大値 Returns: Map: 作成した地図のMapオブジェクト """ # Mapオブジェクトの作成(日本地図全体が表示されるような位置と倍率を指定) map = folium.Map(location=[39.00, 137.00], tiles='Cartodb Positron', zoom_start=6) # TopoJSON の利用 _url = "https://raw.githubusercontent.com/smartnews-smri/japan-topography/main/data/municipality/topojson/s0010/prefectures.json" # 全国都道府県 topo_json_data = requests.get(_url).json() # MapオブジェクトにTopoJSONデータを追加 folium.TopoJson(topo_json_data, "objects.prefectures").add_to(map) # Choroplethの作成 cp = folium.Choropleth(geo_data=topo_json_data , topojson='objects.prefectures' # GeoJSONへ変換するデータの位置 , data=rows # 地域区分するデータ , key_on='properties.N03_001' # 地域を特定するキー , bins=range(0, int(max_value + 2), 1) # カラーマップ , fill_color='PuRd' # カラーマップの色 , fill_opacity=0.3 # 透明度 , line_weight=2, # 境界線の幅 ) cp.add_to(map) # Mapオブジェクトに追加 # TopoJSONの地域データに定当データを追加(ツールチップに表示するため) # TopoJSONのgeometriesに都道府県のデータがあるのでそこのpropertisに要素追加 teito = dict(rows) # リストを辞書化 for d in topo_json_data["objects"]["prefectures"]["geometries"]: # "properties"の辞書に定当のキーと値を追加(都道府県名をキーにして定当を取得) d["properties"]["teito"] = teito[d["properties"]["N03_001"]] # ツールチップの追加 folium.GeoJsonTooltip(['N03_001', 'teito'], ['地域', '人数']).add_to(cp.geojson) # カラーマップの幅を指定(地図を並べて表示した時に長くなるため) cp.color_scale.width = 200 # ブログ埋め込み用iframeの作成 作成したテキストを埋め込めば地図が表示される(色分けされなかった) # iframe = map._repr_html_() # with open("ifram.txt", "w", encoding='utf-8') as f: # f.write(iframe) map.show_in_browser() # こちらなら表示できるけど添付ファイルが残る return map rows_c, rows_i, name_c, name_i, title, max_value = get_csv_from_web() Choropleth_map_topo(rows_c, max([x[1] for x in rows_c]))
◆定点把握疾患の定点あたりの報告数をwebから取得
定点把握疾患の定点あたりの報告数は、NIID国立感染症研究所が出している「IDWR速報データ」(リンク:速報データ )から取得します。データは CSV ファイルです。
このサイトの「定点把握疾患(週報告)、報告数、定点当たり報告数、都道府県別」に貼られているリンクからダウンロードできます。
ここでは、 urllib.request.urlopen()
メソッドを使用してネットワーク上から取得します。
定点当たり報告数は定当と略されています。
CSV の URL は次のような構成をしています。
https://www.niid.go.jp/niid/images/idwr/sokuho/idwr-年/年週/年-週-teiten.csv
年は西暦の下2ケタ、週はその年の何週目かを指定します。
データは約2週間後に公開されます。
そのためデータが取得できないことを考慮する必要があります。
データが取得できない場合、urlopen()
メソッドの戻り値の url 属性に指定した url と異なる値が返るのでそれで判断します。
取得後、
・新型コロナデータ(都道府県名と定当のタプルのリスト)
・インフルエンザデータ(都道府県名と定当のタプルのリスト)
を作成します。
CSV データには見出し行が複数行設定されているのでそれらを考慮します。
作成したデータを folium で使用します。
新型コロナのデータは 2023年5月8日以降から追加されました。
それ以前はデータがないのでそのことを考慮します。
また、都道府県によっては、報告がない場合があります。こちらも考慮します。
考慮の方法はコードで確認してください。
◇CSVデータ
NIID国立感染症研究所のサイトから取得するデータは次のような構成です。
※こちらの記事のアプリで表示しています・・・CSV viewerアプリの作り方(ドラッグアンドドロップ)【Python】 🔗
【CSVの構成】
- 行
- 列
- 1列目:都道府県名
- 2列目:インフルエンザの報告数
- 3列目:インフルエンザの定当数
- 38列目:COVID-19の報告数
- 39列目:COVID-19の定当数
◇手順
- 引数で指定された日付から年と週を取得
date クラスのstrftime()
メソッドで書式を指定して取得
書式は、%Y
:西暦4桁、%U
%V
:週番号 - web から CSV ファイルを開く:
urllib.request.urlopen()
- 戻り値のオブジェクトの
url
属性が要求した url と異なっていたらエラーとして戻る - 1行目を読み飛ばし:
next()
- 2行目を読み地図のタイトルとして保存
データは shift-JIS なのでデコードが必要:decode()
カンマ区切りなのでカンマで分割して1つ目のデータを取得
ダブルクォーテーションを削除:replace()
- 3行目を読み感染症名として保存(データの扱いは同上)
- 4行目、5行目を読み飛ばし:
next()
- 残りの行を一括で読み込み:
read()
- データは shift-JIS なのでデコード:
decode()
- 行ごとに分割:
splitlines()
- データは shift-JIS なのでデコード:
- 戻り値のオブジェクトの
- 新型コロナのデータ作成
都道府県名と定当のタプルを都道府県分のリストで作成:内包表記[ for in if ]
定当のデータがない時は作らない
定当のデータは文字なので実数に変換 - インフルエンザのデータ作成(作成方法は同上)
◇コード:定点把握疾患の定点あたりの報告数をwebから取得
def get_csv_from_web(self, today:date) -> Tuple[list, list, str, str, str, str]: """ 定点把握疾患の定点あたりの報告数をWebから取得 Args: date: 初期表示日付 Returns: list: 新型コロナデータ(都道府県と報告数のタプルのリスト) list: インフルエンザデータ(都道府県と報告数のタプルのリスト) str: 感染症名 str: 感染症名 str: 期間 str: エラーメッセージ(エラーなしの時は空文字) """ msg ="" # today = datetime(2023, 10, 16) year = today.strftime('%Y') week = today.strftime('%V') # csvファイルのurl _url = f'https://www.niid.go.jp/niid/images/idwr/sokuho/idwr-{year}/{year}{week}/{year}-{week}-teiten.csv' # csvファイルの取得 with urllib.request.urlopen(_url) as res: if res.url != _url: msg = "指定した日付の週にデータがありません" return None, None, None, None, None, None, msg # ヘッダに対する処理 next(res) # 1行目 title = next(res).decode('cp932').split(',')[0].replace('"', '') # 2行目 報告期間 shippei = next(res).decode('cp932').split(',') # 3行目 疾病 if len(shippei) > 37: # 2023/5/8以前のデータはない name_c = shippei[37].replace('"', '') # 新型コロナ else: name_c = "" name_i = shippei[1].replace('"', '') # インフルエンザ next(res) # 4行目 next(res) # 5行目 data = res.read() # 残りをすべて読む data = data.decode('cp932') # urlopenで読んだ場合はデコードが必要 data = data.splitlines() # 行ごとに分ける # 新型コロナのデータ作成(データがあるものだけ、報告がないと「-」が設定されるので弾く) if len(shippei) > 37: # 2023/5/8以前のデータはない rows_c = [(row[0], float(row[38])) for row in csv.reader(data) if row[38] and row[38] != "-"] # 都道府県とCOVID-19定当を取得 else: rows_c = [] # インフルエンザのデータ作成(データがあるものだけ、報告がないと「-」が設定されるので弾く) rows_i = [(row[0], float(row[2])) for row in csv.reader(data) if row[2] and row[2] != "-"] # 都道府県とインフルエンザ定当を取得 return rows_c, rows_i, name_c, name_i, title, msg
◆地図を2つ並べて表示
地図を2つ作成し、並べて表示する方法を説明します。
folium のドキュメントにあるサンプルを元にしているだけなので、簡単に説明します。
サンプルでは、branca.element の Figure クラスを使用していますが、folium にも Figure クラスがあるのでそちらを使いました。多分同じだと思います。
まず、全体を描画する Figure オブジェクトを作成します。
次に、Figure オブジェクトに入れる Div オブジェクトを作成します。
Div オブジェクトは配置を指定して2つ作成します。
あわせて Div オブジェクトにタイトルを追加します。
タイトルは HTML を文字列で作成し、親となる地図に追加します。
追加は、get_root()
メソッドで親を探し、html
属性の add_child()
メソッドで行います。
html
属性については、詳細を調べていません。ご容赦ください。
ここで出てきた Figure や Div は、branca パッケージで提供されています。
◇手順
- Figure インスタンスを作成
- Figure オブジェクトに Div オブジェクトを追加:
add_subplot()
2つ作成して表示位置を分ける - 色分け地図を作成:
Choropleth_map_topo()
(自作メソッド)
2種類の地図を作成 - 色分け地図を Div オブジェクトに追加:
add_child()
- タイトルを作成
- タイトル用 HTML 文字列を作成
- 色分け地図の親の
html
属性に追加:add_child()
- 地図の表示
Figure オブジェクトはshow_in_browser()
メソッドを持たないので、ファイルに保存して表示- 保存:
save()
- ブラウザに表示:
webbrowser.open()
- 保存:
◇コード:地図を2つ並べて表示
import folium import webbrowser def tow_choropleth(rows_c, rows_i, name_c, name_i, title, max_value): f = folium.Figure() sb1 = f.add_subplot(1, 2, 1) sb2 = f.add_subplot(1, 2, 2) m1 = Choropleth_map_topo(rows_c, max_value) m2 = Choropleth_map_topo(rows_i, max_value) # add_child タイトルより先じゃないとタイトルが出ない sb1.add_child(m1) sb2.add_child(m2) # タイトルを追加 title_html = f''' <h3 align="center" style="font-size:20px"><b>{name_c}定点当たり報告数</b></h3> <h6 align="right";">{title}</h6> ''' m1.get_root().html.add_child(folium.Element(title_html)) title_html = f''' <h3 align="center" style="font-size:20px"><b>{name_i}定点当たり報告数</b></h3> <h6 align="right";">{title}</h6> ''' m2.get_root().html.add_child(folium.Element(title_html)) # 地図htmlをファイルに保存 f.save('maptest.html') # HTMLファイルをブラウザで表示 webbrowser.open('maptest.html') # 開くのが早すぎで出てこないことがある
◆アプリとしての作り込み
アプリとしては次節のような機能、特長を設けました。
NIID国立感染症研究所が提供しているデータは、約2週間前のものが最新なので、カレンダーの初期値を16日前にしました。
過去の色分け地図を作成できるように日付の指定ができるようにするにあたり、tkcalendar パッケージを利用しました。
tkcalendar の使い方はコードで確認してください。・・・tkcalendar パッケージの説明は⤵
日付を指定後、地図作成ボタンが押されたら地図を作成します。
◇機能・特長
- 新型コロナとインフルエンザの定点あたり報告数を色分け地図(階級区分図)でブラウザ表示します
- 地図上にツールチップで報告数を表示します
- 週(日付を指定)を指定して作成できます
- 報告数の上限を固定して作成できます
- 新型コロナ、インフルエンザの一方だけを作成することができます
◇手順
- 色分け用データの取得:
get_csv_from_web()
(自作メソッド) - エラーがあったら戻る:
msg
が空でなければエラー - 感染症名のチェックが一つも無かったら戻る
- 色分け用データの最大値を求める:
max()
- 最大値を固定にするチェックが付いていたら固定にする
ただし、色分けデータの最大値より小さくしない(エラー回避) - 地図作成
チェックされた状態に依りメソッドを変えて呼び出し
◇コード:地図作成
▽カレンダー、ボタンの作成(MyFrame クラスのコンストラクタ)
# カレンダー 最新データは今日の16に前の週からなのでカレンダーの初期値とする latest_date = date.today() - timedelta(days=16) self.tkcal = DateEntry(self, year=latest_date.year , month=latest_date.month , day=latest_date.day , date_pattern='y/m/d' , locale='ja_JP') self.tkcal.pack() # 作成ボタン btn_exe = tk.Button(self, text='地図作成', command=self.create_map) btn_exe.pack()
▽MyFrame クラス
def create_map(self): """ 地図作成(カレンダーから日付を取得して地図を作成) """ self.var_msg.set("") self.update_idletasks() today = self.tkcal.get_date() msg = self.ctrl.create_map(today) self.var_msg.set(msg)
▽Mapping クラス
def create_map(self, today:date) -> str: """ 地図作成 Args: date: 報告者数報告日 Returns: str: 実行結果のメッセージ """ rows_c, rows_i, name_c, name_i, title, msg = self.get_csv_from_web(today) # エラーがあったら戻る if msg: return msg # 感染症にチェックが無かったら戻る if self.view.var_col.get() == False and self.view.var_flu.get() == False: return "感染症の両方か、どちらかにチェックを付けてください" # 定当の最大値 max_c = max([x[1] for x in rows_c], default=0) max_i = max([x[1] for x in rows_i]) # 最大値を固定にする場合 if self.view.var_fix_max.get(): max_c = max_i = max(40, max_c, max_i) # どの感染症を対象にするかで出す地図を分ける if self.view.var_col.get() and self.view.var_flu.get(): # 新型コロナとインフルエンザ self.tow_choropleth(rows_c, rows_i, name_c, name_i, title, max_c, max_i) elif self.view.var_col.get(): # 新型コロナ self.Choropleth_map_topo(rows_c, name_c, title, max_c, True) elif self.view.var_flu.get(): # インフルエンザ self.Choropleth_map_topo(rows_i, name_i, title, max_i, True) print('finished') return "地図をブラウザに表示しました"
◆GeoJSONとTopoJSON
GeoJSON は、JSON を用いて GIS (地理情報システム)データを記述したファイルフォーマットです。
属性にはポイント(住所や座標)、ライン(各種道路や境界線)、 ポリゴン(国や地域)などが含まれます。
TopoJSON は、GeoJSON の拡張であり、トポロジー(連続性や収束性が定義可能な空間)を記述します。
GeoJSON は経度緯度の配列をデータとして持っていて、ポイントやライン、ポリゴンを描くことができます。
TopoJSON はアーク(弧線)の配列を持っています。 しかも境界線のデータを共有するなどして、GeoJSONに比べてデータ量が格段に少なくなります。
ここでは、データ量の少ない TopoJSON データを使います。
GeoJSON データを使う場合も簡単に触れます。
◇データの入手
データは、いろいろな方が作成して公開してくれています。
GitHub で公開されている場合は、データの raw を表示してその URL を使います。
公開されているデータのいくつかを紹介します。
いずれも GeoJSON、TopoJSON とも提供されています。
日本全体を1ファイルで取れます
GitHub - smartnews-smri/japan-topography:
日本の行政区画(市区町村)・選挙区の地形ファイルをTopoJSONとGeoJSONで公開します。
「N03-21」で始まるファイルは県ごとのファイルです
日本全体は「prefectures.json」ファイルですファイルが市区町村に分かれています
GitHub - niiyz/JapanCityGeoJson: GeoJson of Japanese cities. and TopoJson.
◇データの構造(TopoJSON)
色分け地図を作成する場合、データの構造を知っておく必要があります。
ここでは、前述の smartnews-smri から提供されている TopoJSON データの構造を紹介します。
"type":"Topology", "arcs":[], "transform":{ "scale":[], "translate":[] }, "objects":{ "prefectures":{ "type":"GeometryCollection", "geometries":[ { これが県数分ある "arcs":[], "type":"MultiPolygon", "properties": { "N03_001":"県名" } }, ... ] } }
◆foliumパッケージ
Python で地図を表示するために folium パッケージを使用します。
folium は、Leaflet.js という JavaScript ライブラリを利用する HTML を作成して地図を出力します。
- インストール:
pip install folium
- インポート :
import folium
- 仕様 :Folium — Folium 0.1.dev1+g9ab63f7 documentation
◇GeoJsonクラス
◎コンストラクタ
- 【構文】
GeoJson(data, style_function, highlight_function, name, overlay, control, show, smooth_factor, tooltip, embed, popup, zoom_on_click, marker, **kwargs)
- よく使う使い方(サンプル)
【構文】GeoJson("https://raw.githubusercontent.com/???/geo.json")
- 主な引数
◇TopoJsonクラス
◎コンストラクタ
- 【構文】
TopoJson(data, object_path, style_function, name, overlay, control, show, smooth_factor, tooltip)
- よく使う使い方(サンプル)
【構文】TopoJson(topo_json_data, "objects.prefectures")
- 主な引数
data
:プロットする TopoJSON データ。必須
GeoJSON のような web から読む機能なしファイル
:データはファイルを読み込み使用dict
:データは JSON に変換され使用str
:データはそのまま使用
object_path
:TopoJSON データの geometries を子に持つオブジェクトを示す objects からのパス。必須
◇Mapクラス
◎コンストラクタ
- 【構文】
Map(location, width, height, left, top, position, tiles, attr, min_zoom, max_zoom, zoom_start, min_lat, max_lat, min_lon, max_lon, max_bounds, crs, control_scale, prefer_canvas, no_touch, disable_3d, png_enabled, zoom_control, **kwargs)
- 主な引数
location
:地図の緯度と経度のタプルかリスト(北緯、東経)zoom_start
:地図の初期ズームレベルtiles
:使用するマップタイルセット。デフォルト:"OpenStreetMap"
◎メソッド
show_in_browser()
デフォルトブラウザで表示。下記のようなファイルが作られる
ユーザー/AppData/Local/Temp/folium_a8jdrfot.html
save(outfile, close_file=True)
HTMLをoutfileファイルに保存outfile
:str, bytes, Path型の時は作成、それ以外(ファイル型)はそのまま使用
◇Choroplethクラス
◎コンストラクタ
【構文】
Choropleth(geo_data, data, columns, key_on, bins, fill_color, nan_fill_color, fill_opacity, nan_fill_opacity, line_color, line_weight, line_opacity, name, legend_name, overlay, control, show, topojson, smooth_factor, highlight, use_jenks, **kwargs)
主な引数
geo_data
:GeoJSON ジオメトリへの URL、ファイル パス、またはデータ (json、dict、geopandas など)topojson
:TopoJSON を使用する場合、「objects.yourfeature」を指定
指定すると GeoJSON への変換が有効になる
「objects.yourfeature」は JSON ファイルを確認して求めるdata
:GeoJSON にバインドするデータ- Pandas の DataFrame 型(2次元の型)
- Series 型(1列分の型)
- dict()で辞書にできるデータ(これだとpandasを使わない)
- キーと値のペア(タプル (key, value) など)のリスト
例:[('k1',1), ('k2', 2), ('k3', 3)]
- キーのリストと値のリストから
keys = ['k1', 'k2', 'k3'];values = [1, 2, 3];
dict(zip(keys, values))
- キーと値のペア(タプル (key, value) など)のリスト
key_on
:data とバインドする geo_data のキーを指定(feature の子孫)fill_color
:エリアの色
"BuGn"
,"BuPu"
,"GnBu"
,"OrRd"
,"PuBu"
,"PuBuGn"
,"PuRd"
,"RdPu"
,"YlGn"
,"YlGnBu"
,"YlOrBr"
, and"YlOrRd"
.columns
:データが Pandas DataFrame の場合、バインドされるデータの列をタプルで指定
(キーになる列, 値になる列)bins
:色分けの仕方。デフォルト:6int
:何段階に色分けするかの値。最小値と最大値の間を等間隔に分けるシーケンス
:色分けする境界の値を直接定義
例:[3, 4, 9, 11]
データの範囲より指定が狭いと例外が発生str
:"stone"
,"auto"
,"doane"
,"fd"
,"rice"
,"scott"
,"sqrt"
,"sturges"
設定値はこちらを参照:numpy.histogram_bin_edges — NumPy v1.26 Manual
◇GeoJsonTooltipクラス
◎コンストラクタ
- 【構文】
GeoJsonTooltip(fields, aliases, labels, localize, style, class_name, sticky, **kwargs)
- 主な引数
fields
:表示したい GeoJson/TopoJson の「プロパティ」または GeoPandas GeoDataFrame 列のラベルのシーケンスaliases
:フィールドのキーの代わりにフィールド名としてツールヒントに表示するオプションのエイリアスのシーケンス
◇Figureクラス(brancaパッケージ)
描画する内容を入れるためのクラスです。
◎コンストラクタ
- 【構文】
Figure(width, height, ratio, title, figsize)
- 主な引数
add_subplot(x, y, n, margin=0.05)
分割サブプロットの作成(matplotlibスタイル)x
:グリッドの行数y
:グリッドのカラム数n
:セル番号(1-x*y)
save(outfile, close_file=True)
html ファイルに保存outfile
:ファイルまたはファイル名
◆Tkinterの使い方
Tkinter(ティーキンター)は Python が標準で提供している GUI パッケージです。
他のプログラムの開発ツールで提供されているようなルック&フィールな GUI ツールではありません。
従って、画面を構成するには、すべてコードを書く必要があります。
Tkinter を使用するには import が必要です。
- インポート:
import tkinter as tk
慣例的に tk と別名を付けるようです。
◇Tkinterの使用ウィジェット
Tkinter がサポートする GUI の部品をウィジェット (widget) と呼びます。
ここでは次のウィジェットを使用しています。
◇使用ウィジェット
ウィジェットは基本的にインスタンスを作成し、表示テキストや表示方法などを指定して使用します。
今回使用しているウィジェットです。
パッケージ | ウィジェット名 | 用途 | 見た目 |
---|---|---|---|
tkinter | Frame フレーム |
ウィジェットの受け皿 | |
tkinter | Label ラベル |
文字、画像の表示 | |
tkinter | Button ボタン |
押すと処理が動くボタン | |
tkinter | Checkbutton チェックボックス |
チェックでオン/オフを設定 | |
tkcalender | DateEntry 日付選択エントリ |
日付を設定 |
◇画面構成 - フレーム構造
プログラムを作るにあたって、どのような画面にするか決めなくてはなりません。画面構成を考えるということですね。
画面を構成するというのは、GUI 部品(ウィジェット)を画面に配置することです。
ウィジェットは設定したテキストに合わせてサイズが決まるので、そのまま使用しても画面構成上問題ないものと、広げないと見栄えが良くないものが出てきます。
今回の画面構成です。
- lbl_title (Label) :タイトル表示
- tk_cal (DateEntry) :日付指定エントリー
- btn_exe (Button) :画像作成ボタン
- chb_fix_max (CheckButton) :最大値を固定するチェックボックス
- chb_col (CheckButton) :新型コロナ出力チェックボックス
- chb_flu (CheckButton) :インフルエンザ出力チェックボックス
- lbl_msg (Label) :メッセージ表示
※「lbl_strings」などはプログラムで使用した変数名です。()内はクラス名です。
◇ウィジェットの配置 - pack
▶説明は別記事を参照してください
📖 ウィジェットの配置 - pack - SQLクライアントアプリの作り方(Tkinterで表)【Python】 🔗
◇動作をウィジェットに割り当てる - バインド
▶説明は別記事を参照してください
📖 動作をウィジェットに割り当てる - Excel viewerアプリの作り方(Tkinterでタブと表)【Python】 🔗
◆tkcalendarパッケージ
Tkinterで使えるカレンダーダイアログです。
Tkinterで使える Calendar と DateEntry ウィジェットを提供しています。
- インストール:
pip install tkcalendar
- インポート :
from tkcalendar import Calendar, DateEntry
◇Calendarウィジェット
◎コンストラクタ
- 【構文】
Calendar(master=None, **kw)
- 主な引数
get_date()
:選択されている日付を文字列で返す
◇DateEntryウィジェット
ドロップダウンカレンダーを使用した日付選択エントリです。
◎コンストラクタ
- 【構文】
DateEntry(master=None, **kw)
- 引数
master
:親ウィジェットkw
:Calendarと同等の引数
◎メソッド
get_date()
:表示されている日付をDate型で返す
◆ソースの取得
全体のソースはこちらから取得できます。
- ソース:
Fixed_point_disease.py
- サンプルソース:
folium_sample.py
- 取得先:GitHub - juu7g/Python-map-disease
◇ご注意
本記事は次のバージョンの下で動作した内容を基に記述しています。
- Python 3.8.5
- folium 0.14.0
- tkcalendar 1.6.1
◇免責事項
ご利用に際しては、『免責事項』をご確認ください。
お気づきの点がございましたら『お問い合わせ』からお問い合わせください。
◆さいごに
アプリの記事を投稿してから本記事を投稿するまでに時間が掛かってしまいました。
もし、お待ちいただいている方がいらっしゃいましたら申し訳ございませんでした。
予想以上にてこずってしまいました。
folium の使い方とかを調査していると GeoPandas と言うパッケージの存在に気が付きます。
次は、GeoPandas を使ったものを作ってみようかと思っています。
◆参考
- 仕様書
- 使い方
- foliumの基本的な使い方とオープンデータ活用 #Python - Qiita
- foliumを使って東京23区ラーメンスコアを可視化する #Python - Qiita
- Pythonのfoliumで簡単に地理情報を可視化できる - くそ記事
- Pythonライブラリのfoliumでサクッとクールなヒートマップを作ってみる|narudesu
- Folium とGeoJson を使って 都道府県の形を描画する - ken ohwada 雑記帳
- TopoJSONの例がある:
Folium とTopoJson を使って 都道府県の形を描画する - ken ohwada 雑記帳 - GeoJSONの説明:
オンラインマップを利用したGeoJSONデータのプロット | mLAB - タイトル表示:Easy way to add title for folium maps
- 感染症報告数のデータ
NIID国立感染症研究所が出している「IDWR速報データ 週ごと」
下記は最新週(履歴あり)
速報データ