文京区の子どもの予防接種_指定医療機関一覧をTableauでマッピングしてみる

こんにちは。

先日は文京区の保育園内定指数を2回マッピングしてみました。

data-analytics.hatenablog.com

data-analytics.hatenablog.com

 

今回はTableauのマップ機能を使って、文京区の子どもの予防接種_指定医療機関一覧を地図上にプロットしてみたいと思います。

 

というのも、文京区の子どもの予防接種の指定医療機関一覧も、前回同様PDFの表で表現されていて、ぱっと見どこにあるのかわからないのです。

こういうのを地図上に表示させて、かつどの予防接種がうけられるかまで表現できれば、かなり便利かなと思います。

■文京区_子どもの予防接種の指定医療機関一覧

https://www.city.bunkyo.lg.jp/var/rev0/0208/8407/030104kodomo.pdf

f:id:kei_t__0107:20210114165113p:plain

 

流れとしては以下の通りです。

  1. 文京区_子どもの予防接種の指定医療機関一覧のPDFデータをテーブルデータに変換する
  2. 医療機関の住所情報から緯度経度情報を加える
  3. Tableau上でマッピング&ビジュアライズ

 

文京区_子どもの予防接種の指定医療機関一覧のPDFデータをテーブルデータに変換する

上記PDFをWordで保存⇒表部分をExcelに張り付けて整形しました。

令和3年1月4日時点のものです。

「030104kodomo.xlsx」という名前にしました。

※後ほど緯度経度を加えるため、住所に東京都文京区を加えた「住所変換」という列を追加してます。

f:id:kei_t__0107:20210114165737p:plain

 

医療機関の住所情報から緯度経度情報を加える

前の記事にも書きましたが、Tableauで地図情報を表現する場合、都道府県や区レベルまでなら文字情報で問題ないのですが、 町域や丁目・番地・号レベルでのマッピングになると緯度経度や郵便番号が必要になります。

医療機関所在地毎に緯度経度を付加したく、今回は以下のサイトからAPIを経由してジオコーディングしたいと思います。

※前回は番地レベルで簡単に付与しましたが、番地が被るものが結構あったので、今回はAPIを使って号レベルで一気に付与したいと思います

 

以下のGeocodingという無料のジオコーディングAPIサービスを利用します。

www.geocoding.jp

 

今回はPythonを使ってAPIから緯度経度情報を一括で持ってきたいと思います。

コーディング方法はこちらを参考にさせて頂きました。

qiita.com

 

実行環境はWindows10で、Anacondaをインストールして実行しました。

import requests
from bs4 import BeautifulSoup
import time
import tqdm
import pandas as pd

URL = 'http://www.geocoding.jp/api/'

#複数住所から緯度経度取得
def coordinate(address):
     """
    addressに住所を指定すると緯度経度を返す。
    
    >>> coordinate('東京都文京区本郷7-3-1')
    ['35.712056', '139.762775']
    """
    payload = {'q': address}
    html = requests.get(URL, params=payload)
    soup = BeautifulSoup(html.content, "html.parser")
    if soup.find('error'):
        raise ValueError(f"Invalid address submitted. {address}")
    latitude = soup.find('lat').string
    longitude = soup.find('lng').string
    return [latitude, longitude]


def coordinates(addresses, interval=10, progress=True):
    """
    addressesに住所リストを指定すると、緯度経度リストを返す。
    
    >>> coordinates(['東京都文京区本郷7-3-1', '東京都文京区湯島3丁目30−1'], progress=False)
     [['35.712056', '139.762775'], ['35.707771', '139.768205']]
    """
    coordinates = []
    for address in progress and tqdm(addresses) or addresses:
        coordinates.append(coordinate(address))
        time.sleep(interval)
    return coordinates


#医療機関リストファイル読み込み
df = pd.read_excel(r"***\030104kodomo.xlsx") #***の部分は030104kodomo.xlsxファイルを置いている場所

#APIから緯度経度付与
latlon_list = coordinates(df.loc[:, "住所変換"], progress=False)

#元のdfに緯度経度を結合,latlon_listはリスト形式で普通にやると結合できないのでpd.DataFrame形式に変換する
df = pd.concat([df, pd.DataFrame(latlon_list, columns=["緯度","経度"])], axis=1)

#出力
df.to_excel(r"***\030104kodomo_update.xlsx", index=False) #***の部分は030104kodomo_update.xlsxファイルを出力した場所

 ※TableauではなくPythonマッピングまですればよいのでは?と思った方もいらっしゃるかもですが、Tableau DATA Saber Boot Campの一環でこの記事を書いています

 

 上記が上手くできると、以下のような形でファイルが出力されます。

f:id:kei_t__0107:20210114220833p:plain

ただ、予防接種の名前が微妙におかしいので(I不P活V化ポリオとかになってる。PDF読み込み時のエラー)、手修正します。

f:id:kei_t__0107:20210115111243p:plain

これで下準備完了です。

Tableau上でマッピング&ビジュアライズ

いよいよTableauで読み込みます。

読み込んだら、予防接種の部分を後で使いやすいようにピボット(横持ち⇒縦持ち)します。

◇ピボット前

f:id:kei_t__0107:20210115114849p:plain

◇ピボット後

f:id:kei_t__0107:20210115115135p:plain

 

あとは医療機関を予防接種の実施数で色分けできるようにしたいので、○×形式になっている実施有無を数値(0/1)に変換しておきます。

f:id:kei_t__0107:20210115115638p:plain

 

最後に地図上にマッピングしていきます。「文京区_予防接種対応医療機関マップ」というシートです。

  • 地理的役割を追加した上で列に「経度」、行に「緯度」追加⇒マップ自動生成
  • マップレイヤーでスタイル:ストリート、ウォッシュアウト70%で設定
  • 医療機関名」「住所」「電話番号」をマークの「詳細」に追加
  • 「予防接種実施数」をマークの「色」に追加。色合いを指数が高いほど濃く、低いほど薄く表現する
  • 別途「予防接種実施有無」というシートを作り、「予防接種名」を行に、「実施有無」(○×がついた列)をマークの「形状」「色」に追加。○は赤、×は青、形状も一致させる。
  • 上記のシートを「ツールヒント」内に挿入する ※緯度経度も外しておく
  • 「文京区_予防接種対応医療機関マップ」「予防接種実施有無」ダッシュボード化して連動させる

f:id:kei_t__0107:20210115142650p:plain

f:id:kei_t__0107:20210115142431p:plain

f:id:kei_t__0107:20210115142909p:plain

地図上の医療機関をクリックしたりマウスオーバーすると、詳細データや各予防接種の実施状況が表示される

 

全て出来上がるとこちらになります。

地図上の医療機関をクリックしたりマウスオーバーすると、詳細データや各予防接種の実施状況が表示されます。また、各予防接種の実施状況は右側にも表示されます。

f:id:kei_t__0107:20210115143505p:plain



ご自身で動かしてみたい方はこちらをご覧ください。

 

 

 

 ※詳細はこちらでもご覧いただけます

public.tableau.com



いかがでしたでしょうか? 感想などありましたら、コメントに記載いただくか上記のTableau・Publicからコンタクトくださいませー。 ではでは。

 

文京区の保育園内定指数をTableauでマッピングしてみる その2

こんにちは。

先日は文京区の保育園内定指数をマッピングしてみました。 今回は前回のデータを元に町域のマッピングや、年齢や年度が比較ができるダッシュボードをTableauで作りたいと思います。

流れとしては以下の通りです。

  1. 町域のマッピング
  2. 保育園内定指数の比較ダッシュボード作成
  3. 町域の比較ダッシュボード作成
町域のマッピング

前回は保育園毎にマッピングしましたが、地域的な傾向を知りたい、などもあると思います。 そこで郵便番号ベースの町域情報を使ってマッピングしてみたいと思います。 やり方は前回の保育園マッピングとほぼ同じです。 違いとしては、以下の通りです。

  • 内定指数(数値のみ)を作る ※INT([内定指数])
  • 郵便番号をマークの詳細に持ってくる
  • 郵便番号基準地域をマークのラベルに持ってくる
  • 内定指数(数値のみ)をマークのラベルに持ってくる
  • 形状の「〇円」のサイズを少し大きくする

すると以下のようなマッピングが作れます。 例えば2020年の1歳だと、西片・千駄木・湯島が27.3とかなり内定指数が高い地域となっています。 f:id:kei_t__0107:20210108183505p:plain

ただし、このままだと内定指数を数値のみにしてるので、「定員割れ」「1名のみ」「空きなし」などは反映されません。 こちらをこの地域の丸の中に入れても良いのですが、町域名+3つの数字が並ぶと大分Busyになってしまうので、別途横に棒グラフをいれて対応したいと思います。

  • 「定員割れ比率」を作る⇒ 定員割れ数:IF [内定指数]="定員割れ" THEN 1 ELSE 0 END を元に、SUM([定員割れ数])/COUNT([内定指数])
  • 「1名or空きなし比率」を作る⇒ 1名or空きなし数: IF [内定指数]="(1名)" or [内定指数]="空きなし" THEN 1 ELSE 0 END を元に、SUM([(1名)or空きなし数])/COUNT([内定指数])

出来上がりが以下のダッシュボードになります。 パラメーターを年度や年齢で入れ替えると左のマッピングも右のグラフも同時に変わります。 こうしてみると、千駄木は内定指数も高く、1名or空きなし比率も高い、本当の激戦地域というのが一目でわかりますね。 こういうのを見ながら、引っ越しの検討の際などに狙い目のエリアを探すというのもありかなーと思います。 f:id:kei_t__0107:20210108184851p:plain

実際に操作してみてみたい方はこちらをご覧ください。

※見づらい場合はこちらでもご覧いただけます https://public.tableau.com/views/_ver2_16100996946850/sheet0?:language=ja&:display_count=y&publish=yes&:origin=viz_share_link

保育園内定指数の比較ダッシュボード作成

例えば2020年の1歳のデータを見たとき、過去の2019年や0歳と比較したい、などが出てくると思います。 なので、今回は2つのマッピングデータを比較できるようにしたいと思います。 単純に2つのマッピングシートを並べれば良いかと思うのですが、パラメーターを変えると両方ともデータが変わってしまいます。 なので、2つのパラメーターを作って、それぞれのシートのパラメーターを設定できるようにします。

作ってみると、以下のような形になります。(2020年1歳と0歳の比較:上は1歳、下は0歳) 0歳の方が薄い色の点が多く、明らかに0歳の方が入りやすいことがわかりますね。 やはり一覧で比較できるとわかりやすいです。 f:id:kei_t__0107:20210108222749p:plain

1歳での2019年・2020年を比較してみます。 あまり大きな違いはすぐにはわかりませんが、駒込駅近辺や江戸川橋駅近辺(青枠で囲ったところ)は20年に色が薄くなってます。 この辺りは少し入りやすくなってるのかもしれないです。 f:id:kei_t__0107:20210108223606p:plain

このように2つのプロットを比較すると、より狙い目や厳しい状況のエリアや保育所が見えてきますね。

実際に操作してみてみたい方はこちらをご覧ください。

※見づらい場合はこちらでもご覧いただけます https://public.tableau.com/views/_ver2_16100996946850/sheet4?:language=ja&:display_count=y&publish=yes&:origin=viz_share_link

町域の比較ダッシュボード作成

上記のような比較ダッシュボードを一番上で作った町域のマッピングでもやってみました。

1歳での2019年・2020年も比較してみます。(左が2019年、右が2020年) 全体的に下がってますが、特に本郷・本駒込・関口で大きく下がってます。 f:id:kei_t__0107:20210108225628p:plain

実際に操作してみてみたい方はこちらをご覧ください。

※見づらい場合はこちらでもご覧いただけます https://public.tableau.com/views/_ver2_16100996946850/sheet8?:language=ja&:display_count=y&:origin=viz_share_link

いかがでしたでしょうか? 感想などありましたら、コメントに記載いただくか上記のTableau・Publicからコンタクトくださいませー。 ではでは。

文京区の保育園内定指数をTableauでマッピングしてみる

こんにちは。

現在Tableau DATA Saber Boot Camp(https://datasaber.world/#whois)というものに参加しています。 その中の課題で以下のものがありましたので、ブログ記事&Publicに投稿するネタとして、最近直面した保活をテーマにすると面白いかなと思いました。

  • Tableau Publicに自身で作成したVizを掲載し、そのURLをTwitterでシェアする。
  • Tableauに関連するブログ記事を書き、そのURLをTwitterでシェアする。

私が住んでる文京区では、以下のURLにあるような選考方法で選考指数を算出します。 夫婦フルタイム共働きだと26点(夫婦フルタイム20点+区民4点+新規入園1点+近隣親族無し1点)で、兄弟やひとり親、受諾・待機などで更に加点/減点されます。

文京区 保育園の選考方法について 2021年

そしてこの選考指数を、過去の保育園ごとの内定指数と照らし合わせながら保育園を選びます。 ただ、この過去の内定指数はPDFの表で表示されているのみで、 例えば自分の家に近いのかや気になる園がどの辺にあるのかがパッと見わからない状況になってます。

■2020年内定指数 https://www.city.bunkyo.lg.jp/var/rev0/0208/3737/shisuu2.4.pdf f:id:kei_t__0107:20210107143920p:plain

以下に地図と保育園位置が載ってるので、上記の指数と照らし合わせてみればよいのですが、 一覧性に欠けますし、保育園探しと家探しを両方やろうとするときはかなり面倒です。

■2021年度保育施設マップ https://www.city.bunkyo.lg.jp/var/rev0/0208/3734/map.pdf f:id:kei_t__0107:20210107144536p:plain

上記の問題を解決すべく、今回はTableauのマップ機能を使って、地図上への保育園と内定指数のプロットを試みたいと思います。

流れとしては、以下の通りです。

  1. 内定指数のPDFデータをテーブルデータに変換する(過去2年分)
  2. 保育園住所のPDFデータをテーブルデータに変換し、緯度経度情報を加える
  3. データの整合性チェック
  4. Tableauで1と2のデータを読み込み、inner_join(内部結合)する
  5. Tableau上でマッピング&ビジュアライズ
内定指数のPDFデータをテーブルデータに変換する(過去2年分)

データは以下にあります。

■2020年内定指数 https://www.city.bunkyo.lg.jp/var/rev0/0208/3737/shisuu2.4.pdf

■2019年内定指数 https://www.city.bunkyo.lg.jp/var/rev0/0208/3738/nateishiu2.15.pdf

上記PDF、普通にExcelスプレッドシートにコピペしても上手くいかないので、 Wordで保存⇒表部分をExcelに張り付けて整形しました。

◇Before ※悪名高きセル結合やセル毎の文字分割がされていて辛い f:id:kei_t__0107:20210107150419p:plain

◇After f:id:kei_t__0107:20210107150708p:plain

保育園住所のPDFデータをテーブルデータに変換し、緯度経度情報を加える

データは以下にあります。 ■2020年度保育施設住所・連絡先一覧 ※2019年版が見当たらなかったので2020年のみ https://www.city.bunkyo.lg.jp/var/rev0/0208/5428/ichiran.pdf

上記PDFも同じようにWordで保存⇒表部分をExcelに張り付けて整形しました。

◇Before f:id:kei_t__0107:20210107151432p:plain

◇After f:id:kei_t__0107:20210107151619p:plain

PDFデータから追加した点としては、「緯度経度の情報」「郵便番号」です。 Tableauで地図情報を表現する場合、都道府県や区レベルまでなら文字情報で問題ないのですが、 町域や丁目・番地・号レベルでのマッピングになると緯度経度や郵便番号が必要になります。

保育園所在地毎に緯度経度や郵便番号を付加したく、以下のサイトから付与しました。(ジオコーディングというそうです)

東京大学空間情報科学研究センターが提供する「CSVアドレスマッチングサービス」 newspat.csis.u-tokyo.ac.jp

国土交通省の以下のサイトからデータ引っ張ってきて紐づけても良いかもしれません nlftp.mlit.go.jp

上記の2つは番地レベルでの緯度経度を引っ張ってきています。 ただ、以下の例のように番地まで重複した園も出てきました。

  • グローバルキッズ茗荷谷園 東京都文京区小石川5-38-11
  • ちいさいおうち小石川 東京都文京区小石川5-38-2

このような場合は以下のサイトで号レベルまでの緯度経度を直接調べて上書きしました。※このような細かいチェックが時間かかる www.geocoding.jp

郵便番号については日本郵便の以下のサイトのデータと結合しました。(東京都文京区春日、などの町域レベルで結合) ※ちなみに郵便番号は今回は使わず、次回記事で使用予定です www.post.japanpost.jp

データの整合性チェック

ここまでやるのもかなり大変でしたが、内定指数のデータと保育園住所のデータがきちんと結合しないと意味がありません。 なので、園名が一致するかどうかをチェックしました。

2020年と2019年の内定指数データの園名は特に問題なかったのですが、 内定指数データの園名と保育園住所データの園名が一致しないケースがいくつかあったので、(半角全角違い大文字小文字違い、園名省略、余分な文字等) こちらも修正を加えました。

□違いの例

  • 小学館アカデミー小石川保育園」と「小学館アカデミー小石川保育園」
  • 保育所まあむ東大前園」と「保育所まぁむ東大前園」
Tableauで1と2のデータを読み込み、inner_join(内部結合)する

いよいよTableauで読み込みます。以下のデータを読み込みました。

  1. 2020年内定指数データ
  2. 2019年内定指数データ
  3. 2020年保育園住所データ

1と2のデータはユニオンし、3のデータとリレーションシップを行いました。

◇ユニオン f:id:kei_t__0107:20210107160703p:plain

◇後で使いやすいように内定指数部分をピボット(横持ち⇒縦持ち) f:id:kei_t__0107:20210107161249p:plain

f:id:kei_t__0107:20210107161411p:plain

◇内定指数データと保育園住所データのリレーションシップ f:id:kei_t__0107:20210107161518p:plain

Tableau上でマッピング&ビジュアライズ

最後に地図上にマッピングしていきます。

  • 列に「経度」行に「緯度」追加⇒マップ自動生成
  • マップタブのマップレイヤーでスタイル:ストリート、ウォッシュアウト70%で設定
  • 年度と年齢をパラメータ化&フィルターと連動するようにする ※年度の例:IF [年度]=[年度 のパラメーター] THEN [年度] ELSE NULL ENDの「表示年度」を作りフィルターに入れNULLを除外
  • 「園名」「所在地」をマークの「詳細」に追加
  • 「内定指数」をマークの「色」に追加。色合いを指数が高いほど濃く、低いほど薄く表現する
  • マークの形状を「〇円」にして、サイズを少し大きくする

出来上がりはこちら。 年度を2020年や2019年に切り替えたり、年齢を0歳~5歳で切り替えることができます。 マウスオーバーすると園名や指数の数値が出てきます。 例えば2020年の1歳だと、全般的に26点以上が多そうですが、大塚地域や小規模保育園は点数が低そう、などがわかりますね。 2019年と比較したり、0歳で見てみたりするのも良いかもしれません。

※詳細はこちらでもご覧いただけます public.tableau.com f:id:kei_t__0107:20210107165947p:plain

いかがでしたでしょうか? 次回は地域別の傾向をみたり、経年比較や年齢比較をしてみたいと思います。 感想などありましたら、コメントに記載いただくかコンタクトくださいませー。

ではでは。