TL;DR
-
自治体(文京区)オープンデータから緯度、経度入っているデータセットを抽出しすべて地図上に可視化した
- 試しにインプリしたサイト
- 地図: https://bunkyo.starseeker.blackaplysia.com/
- Orion (GET以外は405を返す):
- entity 100件取得: https://bunkyo-orion.starseeker.blackaplysia.com/v2/entities?limit=100
- 特定のentity取得: https://bunkyo-orion.starseeker.blackaplysia.com/v2/entities/50016
- 特定のentityeをkey-valueで取得: https://bunkyo-orion.starseeker.blackaplysia.com/v2/entities/50016?options=keyValues
- 利用したおもなツール
- StarSeeker: Next.js+PostgreSQL+FIWAREによりJSONで登録するデータを地図上に表示するソフトウェア
- FIWARE Orion: NGSIをインターフェースとするメッセージブローカー(StarSeekerに同梱)
- dim: オープンデータを管理するパッケージマネージャー
- opdutil: オープンデータのCSVを解析するために今回作成した汎用ツール
おおまなか手順
- StarSeekerをインストールし地図上にデータを可視化するしくみを構築
-
dim
およびopdutil
により、オープンデータからStarSeekerのデータを作成 - StarSeekerにデータを投入
StarSeekerインストール
StarSeekerの説明に沿って地図の表示までを行う。
まず、作業ディレクトリ/work
にgit clone
したのち、環境ファイル~/StarSeeker/StarSeeker/.env
を編集する。(MAP_DEFAULT_*
は文京区役所の位置を設定)
MONGOUSERNAME=mongouser
MONGOPASSWORD=mongopassword
POSTGREUSER=pguser
POSTGREPASSWORD=pgpassword
MAP_DEFAULT_LATITUDE=35.7079305
MAP_DEFAULT_LONGITUDE=139.7524542
MAP_DEFAULT_ZOOM=14
StarSeekerのサーバ群を起動する。
~/StarSeeker/StarSeeker$ docker-compose up -d
ブラウザでhttp://ホスト名:3000
に接続し地図が表示されることを確認(ハンバーガーアイコンからデータセットを選択しようとするエラーが出る)
SiteSeekerのoperatorを準備し起動する。
~/StarSeeker/StarSeeker$ cd operator
~/StarSeeker/StarSeeker/operator$ cp -r samples work
~/StarSeeker/StarSeeker/operator$ ln -s ../.env .env
~/StarSeeker/StarSeeker/operator$ docker-compose up -d
オープンデータの取得と加工
以下は、StarSeekerのoperator端末(op)で行うため、git
用のid_rsa
をdockerホストから転送後、operator端末のシェルに入る。なお、ホスト側がrootでない場合はchown
でownerを変更する。
~/StarSeeker/StarSeeker/operator$ sudo docker exec --user root:root op /bin/mkdir /root/.ssh
~/StarSeeker/StarSeeker/operator$ sudo docker cp ~/.ssh/id_rsa op:/root/.ssh
~/StarSeeker/StarSeeker/operator$ sudo docker exec op /bin/chown root:root /root/.ssh/id_rsa_github
~/StarSeeker/StarSeeker/operator$ docker exec -it op /bin/bash
root@op:/work#
git
の初期設定
dim
およびopdutil
をgit clone
して使用するためgit
の初期設定を行う。
SSH (~/.ssh/config
)の設定
root@op:/work# echo 'Host github.comLF Hostname github.comLF User my.githubuserLF IdentityFile "/root/.ssh/id_rsa"' | sed 's/LF/\n/g' >>/root/.ssh/config
git config
の設定
root@op:/work# git config --global user.name my.name
root@op:/work# git config --global user.email my@email
dim
の準備
オープンデータパッケージマネージャーのdim
を導入する。dim
はdeno環境で動作するため、まずdeno
、その後dim
をインストールする。
deno
のインストール
root@op:/work# cd ~
root@op:/root# curl -fsSL https://deno.land/install.sh | sh
root@op:/root# echo 'export DENO_INSTALL="/root/.deno"' >>~/.bashrc
root@op:/root# echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >>~/.bashrc
root@op:/root# source ~/.bashrc
dim
のインストール
作業ディレクトリ/work
に戻り、dim
をインストールする。
root@op:/root# cd /work
root@op:/work# git clone git@github.com:c-3lab/dim.git
root@op:/work# cd dim
root@op:/work/dim# deno install --unstable --allow-read --allow-write --allow-run --allow-net dim.ts
文京区のオープンデータからStarSeeker用ファイルを生成
opdutil
のインストール
作業ディレクトリにオープンデータ加工ユーティリティopdutil
をインストールする。
root@op:/work/dim# cd /work
root@op:/work# git clone git@github.com:mkyutani/opdutil.git
root@op:/work# cd opdutil
root@op:/work/opdutil# pip3 install .
dim
の初期化
opdutil
のディレクトリでdimを初期化する。
root@op:/work/opdutil# dim init
文京区オープンデータの一括取得
opdlist
にオープンデータHTMLページのURLを渡すと、そのHTML中に含まれるCSVファイルのリンクとその周辺にあるデータ名称の2つ組がCSV形式で出力される。
root@op:/work/opdutil# opdlist https://www.city.bunkyo.lg.jp/kusejoho/opendata/portalsite.html
https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/07metadata/metadata.csv,メタデータ(Excelファイル; 19KB)|(CSVファイル; 9KB)
https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/01shukaishisetsu/syukaishisetsu.csv,集会施設 (Excelファイル; 16KB)|(CSVファイル; 4KB)
...
この出力結果を加工しdim install
に渡すことですべてdim
に登録することができる。なお、この例では名前の後ろに余計な文字列(ExcelファイルとかCSVファイルとか)がついているためsed
で削除しておく。
root@op:/work/opdutil# opdlist https://www.city.bunkyo.lg.jp/kusejoho/opendata/portalsite.html | sed 's/[((].*[))]//; s/,/ -n /' | while read line; do sh -c -x "dim install $line"; done
ここでdim
の実行ログを見ると、1件だけ「The name already exists」で失敗。直前のものと同じデータセット名になっていることがわかる。dim
はデータセット名(-n
オプション)が重複した場合は登録できない。
...
+ dim install https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/02b-guru/b-guru-sendagi-komagome.csv -n コミュニティバス「Bーぐる」の時刻表
Installed to ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/02b-guru/b-guru-sendagi-komagome.csv
+ dim install https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/02b-guru/b-guru-mezirodai-kohinata.csv -n コミュニティバス「Bーぐる」の時刻表
The name already exists.
...
そこで、失敗したCSVのデータセット名を変更して再登録する。
root@op:/work/opdutil# dim install https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/02b-guru/b-guru-mezirodai-kohinata.csv -n コミュニティバス「Bーぐる」の時刻表(目白台・小日向)
dim
にすべて登録されたことを確認できた。(dim
はシンプルだが強力なツール!)
root@op:/work/opdutil# dim list -s
メタデータ https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/07metadata/metadata.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/07metadata/metadata.csv
集会施設 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/01shukaishisetsu/syukaishisetsu.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/01shukaishisetsu/syukaishisetsu.csv
コミュニティバス「Bーぐる」の時刻表 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/02b-guru/b-guru-sendagi-komagome.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/02b-guru/b-guru-sendagi-komagome.csv
自転車駐車場 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/03zitensya/zitensyatyusyajo.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/03zitensya/zitensyatyusyajo.csv
公衆無線LAN設置場所 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/04kosyumusenlan/kosyumusenlan.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/04kosyumusenlan/kosyumusenlan.csv
ごみと資源の収集日 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/05syusyubi/syusyubi.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/05syusyubi/syusyubi.csv
ごみと資源の分別品目 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/06bunbetuhinmoku/bunbetuhinmoku.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/06bunbetuhinmoku/bunbetuhinmoku.csv
資源の回収拠点 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/07kaisyukyoten/kaisyukyoten.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/07kaisyukyoten/kaisyukyoten.csv
区内サイクルポート一覧 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/10kunaisaikurupotoitiran/eriabetupotomap.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/10kunaisaikurupotoitiran/eriabetupotomap.csv
保育園 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/02hoikuen/hoikuen.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/02hoikuen/hoikuen.csv
幼稚園 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/01yotien/yotien.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/01yotien/yotien.csv
区立小学校 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/03syogakko/syogakko.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/03syogakko/syogakko.csv
区立中学校 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/04tyugakko/tyugakko.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/04tyugakko/tyugakko.csv
育成室 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/05ikuseishitsu/ikuseishitsu.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/05ikuseishitsu/ikuseishitsu.csv
児童館 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/06zidokan/zidokan.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/06zidokan/zidokan.csv
地域子育て支援拠点 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/07chiikikosodatesienkyoten/chiikikosodatesienkyoten.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/07chiikikosodatesienkyoten/chiikikosodatesienkyoten.csv
キッズルーム https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/08kidsroom/kidsroom.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/08kidsroom/kidsroom.csv
子ども・乳幼児ショートステイ https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/09shortstay/shortstay.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/09shortstay/shortstay.csv
病児・病後児保育ルーム https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/10byojihoikuroom/byojihoikuroom.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/02kosodate-kyouiku/10byojihoikuroom/byojihoikuroom.csv
文化・スポーツ施設 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/03bunka-kankou-sports/01bunka-sports/bunka-sports.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/03bunka-kankou-sports/01bunka-sports/bunka-sports.csv
区立図書館 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/03bunka-kankou-sports/02tosyokan/tosyokan.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/03bunka-kankou-sports/02tosyokan/tosyokan.csv
博物館一覧 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/03bunka-kankou-sports/03hakubutsukanitiran/hakubutsukan.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/03bunka-kankou-sports/03hakubutsukanitiran/hakubutsukan.csv
診療所 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/01shinryojo/shinryojo.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/01shinryojo/shinryojo.csv
歯科診療所 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/02shikashinryojo/shikashinryojo.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/02shikashinryojo/shikashinryojo.csv
施術所 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/03sejutsusyo/sejutsusyo.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/03sejutsusyo/sejutsusyo.csv
薬局 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/04yakkyoku/yakkyoku.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/04yakkyoku/yakkyoku.csv
高齢者あんしん相談センター https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/05koreisyaanshinsodancenter/koreisyaanshinsodancenter.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/05koreisyaanshinsodancenter/koreisyaanshinsodancenter.csv
地域密着型サービス事業所 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/06tiikimittyakugataservicezigyosyo/tiikimittyakugataservicezigyosyo.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/06tiikimittyakugataservicezigyosyo/tiikimittyakugataservicezigyosyo.csv
文京福祉センター https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/07bunkyofukushicenter/bunkyofukushicenter.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/04hoken-fukushi/07bunkyofukushicenter/bunkyofukushicenter.csv
緊急避難場所・避難所 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/01kinkyuhinanbasyo-hinanjo/kinkyuhinanbasyo-hinanjo.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/01kinkyuhinanbasyo-hinanjo/kinkyuhinanbasyo-hinanjo.csv
土のうステーション https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/02donostation/donostation.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/02donostation/donostation.csv
区立公園・児童遊園・遊び場 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/03kouen-asobiba/kuritsukouen-jidouyuuen-asobiba.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/03kouen-asobiba/kuritsukouen-jidouyuuen-asobiba.csv
区内消防署 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/05kunaisyoubousyoichiran/kunaisyoubousyo.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/05kunaisyoubousyoichiran/kunaisyoubousyo.csv
交通事故の年別推移 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/08kotsujikokensunonenbetsusuii/kotsujikononenbetsusuii.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/08kotsujikokensunonenbetsusuii/kotsujikononenbetsusuii.csv
文京区管理橋梁 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/09bunkyokukanrikyoryo/bunkyokukanrikyoryo.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/09bunkyokukanrikyoryo/bunkyokukanrikyoryo.csv
区内公衆便所 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/10kunaikosyubenjyo/kunaikosyubenjyo.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/10kunaikosyubenjyo/kunaikosyubenjyo.csv
AED設置箇所一覧 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/11aedsettikasyoitiran/aedsettikasyoitiran.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/11aedsettikasyoitiran/aedsettikasyoitiran.csv
区設貯水槽一覧表 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/12kusetutyosuisoitiranhyo/tyosuiso.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/05bousai-macidukuri-kankyou/12kusetutyosuisoitiranhyo/tyosuiso.csv
投票場所 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/06kuseijyouhou/06tohyobasyo/tohyobasyo.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/06kuseijyouhou/06tohyobasyo/tohyobasyo.csv
イベント一覧 https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/10sonota/01event/131059_event.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/10sonota/01event/131059_event.csv
コミュニティバス「Bーぐる」の時刻表(目白台・小日向) https://www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/02b-guru/b-guru-mezirodai-kohinata.csv ./data_files/www.city.bunkyo.lg.jp/library/opendata-bunkyo/01tetsuduki-kurashi/02b-guru/b-guru-mezirodai-kohinata.csv
(参考)dim list
のつかいかた
以下ではdim list
を頻繁に使用するため、イディオム的な使い方を説明する。
- 登録されているデータセットの名前を列挙
$ dim list -s | cut -d' ' -f 1
- 名前に「小学校」を含むデータセットのCSVファイルパスを取り出す(パイプで後続のファイルに渡す典型的な使い方)
$ dim list -s | grep 小学校 | cut -d' ' -f 3
- 全データセットから「文京シビックセンター」という文字列のある行を取り出し、ファイル名(basename)を添えて表示
$ for csvpath in `dim list -s | cut -d' ' -f 3`; do cat $csvpath | iconv -f cp932 -t utf-8 | grep -n 文京シビックセンター | sed "s#^#`basename -s .csv $csvpath`::#"; done
なお、最後の例にあるように、一般的にオープンデータCSVファイルの文字コードはWindowsに親和性が高いいわゆるシフトJISであることが多くlinuxでは扱いづらいため、必要に応じてutf-8に変換する。この場合、変換元ファイルの文字コード名はShift_JISではなくCP932が適切であることが多い。(CP932とShift_JISは一部の環境依存文字が異なる)文字コードについてはdim
で登録するときにコマンドラインオプションで指定して変換しておいてもよい。
4つ組(名称、住所、緯度、経度)の取り出しとStarSeeker用ファイルの生成
今回はStarSeekerの地図に表示するため、opddetect
とopdselect
を使い、文京区のデータから(名称、住所、緯度、経度)の4つ組を取り出す。元となるCSVファイルパスとデータセット名を標準入力から渡せるため、dim
からのパイプで渡す。
-
opddetect
の機能: コマンドラインオプション--hint
で指定した正規表現群にマッチする行(CSVヘッダ行)を探し、それぞれのデータを格納したカラム番号を特定する。 -
opdselect
の機能: コマンドラインオプション--hint
で指定した正規表現群にマッチする行で特定したカラムについて、元のファイルからカラム選択して出力する。
ヘッダの推定と該当カラムの特定(opddetect
)
まずは「名」「住所」「緯度」「経度」をもつ行をヘッダと推定し、カラムを特定してみる。
root@op:/work/opdutil# dim list -s | cut -d' ' -f 1,3 | opddetect --encoding cp932 --hint '名,住所,緯度,経度' --csv 2>/dev/null
syukaishisetsu.csv,1,A:施設名,D:住所,E:緯度,F:経度
kosyumusenlan.csv,1,B:名称,C:住所,D:緯度,E:経度
hoikuen.csv,1,B:施設名,E:住所,F:緯度,G:経度
yotien.csv,1,B:施設名,E:住所,F:緯度,G:経度
syogakko.csv,1,B:施設名,E:住所,F:緯度,G:経度
tyugakko.csv,1,B:施設名,E:住所,F:緯度,G:経度
ikuseishitsu.csv,1,A:育成室名称,D:住所,E:緯度,F:経度
zidokan.csv,1,A:施設名,D:住所,E:緯度,F:経度
chiikikosodatesienkyoten.csv,1,A:施設名,E:住所,F:緯度,G:経度
kidsroom.csv,1,A:施設名,D:住所,E:緯度,F:経度
shortstay.csv,1,A:事業名,D:住所,E:緯度,F:経度
byojihoikuroom.csv,1,A:施設名,D:住所,E:緯度,F:経度
bunka-sports.csv,1,A:施設名,D:住所,E:緯度,F:経度
tosyokan.csv,1,A:施設名,D:住所,E:緯度,F:経度
hakubutsukan.csv,1,C:都道府県名,H:住所,I:緯度,J:経度
koreisyaanshinsodancenter.csv,1,A:施設名,D:住所,E:緯度,F:経度
tiikimittyakugataservicezigyosyo.csv,2,B:名 称,E:住所,F:緯度,G:経度
bunkyofukushicenter.csv,1,A:施設名,D:住所,E:緯度,F:経度
kinkyuhinanbasyo-hinanjo.csv,1,A:施設名,C:住所,D:緯度,E:経度
kuritsukouen-jidouyuuen-asobiba.csv,1,A:施設名,C:住所,D:緯度,E:経度
kunaisyoubousyo.csv,1,A:名称,B:住所,C:緯度,D:経度
kunaikosyubenjyo.csv,1,A:公衆便所名,B:住所,C:緯度,D:経度
aedsettikasyoitiran.csv,1,C:都道府県名,F:住所,G:緯度,H:経度
tyosuiso.csv,1,C:都道府県名,F:住所,H:緯度,I:経度
131059_event.csv,1,C:都道府県名,T:住所,U:緯度,V:経度
ここで、たとえば以下の例は、syukaishisetsu.csv
(集会施設)の1
行目がマッチし、Excel形式のカラム番号A
、D
、E
、F
がそれぞれ「施設名」、「住所」、「緯度」、「経度」という値であることを示している。
syukaishisetsu.csv,1,A:施設名,D:住所,E:緯度,F:経度
ヘッダを特定できなかったcsvについてはログ(標準エラー出力)に「No records like hints」と出力されていることが確認できる。
root@op:/work/opdutil# dim list -s | cut -d' ' -f 1,3 | opddetect --encoding cp932 --hint '名,住所,緯度,経度' --csv 2>&1 | grep 'like hints'
metadata.csv: No records like hints
b-guru-sendagi-komagome.csv: No records like hints
zitensyatyusyajo.csv: No records like hints
syusyubi.csv: No records like hints
bunbetuhinmoku.csv: No records like hints
kaisyukyoten.csv: No records like hints
eriabetupotomap.csv: No records like hints
shinryojo.csv: No records like hints
shikashinryojo.csv: No records like hints
sejutsusyo.csv: No records like hints
yakkyoku.csv: No records like hints
donostation.csv: No records like hints
kotsujikononenbetsusuii.csv: No records like hints
bunkyokukanrikyoryo.csv: No records like hints
tohyobasyo.csv: No records like hints
b-guru-mezirodai-kohinata.csv: No records like hints
これらの失敗例の中にも緯度経度をもつものがあるためデータを見ながら試行錯誤を経た結果、緯度経度を含むオープンデータについて以下のコマンドですべてカラム取得できることを確認した。(tyosuiso.csv
(貯水槽)はなんと「備考」に名前が入っていた!?)
root@op:/work/opdutil# dim list -s | cut -d' ' -f 1,3 | opddetect --encoding cp932 --hint '名 *称|施設名|事業名|設置場所|橋梁名|投票所|便所名|イベント名|備考,住所|位置|地,緯度,経度' --csv 2>/dev/null
syukaishisetsu.csv,1,A:施設名,D:住所,E:緯度,F:経度
zitensyatyusyajo.csv,1,A:名称,B:位置,C:緯度,D:経度
kosyumusenlan.csv,1,B:名称,C:住所,D:緯度,E:経度
hoikuen.csv,1,B:施設名,E:住所,F:緯度,G:経度
yotien.csv,1,B:施設名,E:住所,F:緯度,G:経度
syogakko.csv,1,B:施設名,E:住所,F:緯度,G:経度
tyugakko.csv,1,B:施設名,E:住所,F:緯度,G:経度
ikuseishitsu.csv,1,A:育成室名称,D:住所,E:緯度,F:経度
zidokan.csv,1,A:施設名,D:住所,E:緯度,F:経度
chiikikosodatesienkyoten.csv,1,A:施設名,E:住所,F:緯度,G:経度
kidsroom.csv,1,A:施設名,D:住所,E:緯度,F:経度
shortstay.csv,1,A:事業名,D:住所,E:緯度,F:経度
byojihoikuroom.csv,1,A:施設名,D:住所,E:緯度,F:経度
bunka-sports.csv,1,A:施設名,D:住所,E:緯度,F:経度
tosyokan.csv,1,A:施設名,D:住所,E:緯度,F:経度
hakubutsukan.csv,1,E:名称,H:住所,I:緯度,J:経度
koreisyaanshinsodancenter.csv,1,A:施設名,D:住所,E:緯度,F:経度
tiikimittyakugataservicezigyosyo.csv,2,B:名 称,E:住所,F:緯度,G:経度
bunkyofukushicenter.csv,1,A:施設名,D:住所,E:緯度,F:経度
kinkyuhinanbasyo-hinanjo.csv,1,A:施設名,C:住所,D:緯度,E:経度
donostation.csv,1,A:設置場所,B:住所,C:緯度,D:経度
kuritsukouen-jidouyuuen-asobiba.csv,1,A:施設名,C:住所,D:緯度,E:経度
kunaisyoubousyo.csv,1,A:名称,B:住所,C:緯度,D:経度
bunkyokukanrikyoryo.csv,1,A:橋梁名,C:所在地,D:所在地(緯度),E:所在地(経度)
kunaikosyubenjyo.csv,1,A:公衆便所名,B:住所,C:緯度,D:経度
aedsettikasyoitiran.csv,1,E:名称,F:住所,G:緯度,H:経度
tyosuiso.csv,1,K:備考,F:住所,H:緯度,I:経度
tohyobasyo.csv,1,C:投票所,D:所在地,E:緯度,F:経度
131059_event.csv,1,E:イベント名,T:住所,U:緯度,V:経度
カラムの選択(opdselect
)
次に、opddetect
の代わりにopdselect
に同じコマンドラインオプションを渡して、マッチしたカラムのみ選択してみる。(これはまさにSQLのselect
のようなもの)
なお、コマンドラインオプション--csv
を省略するとopdselect
は同じ結果をjsonで出力する。
root@op:/work/opdutil# dim list -s | cut -d' ' -f 1,3 | opdselect --encoding cp932 --hint '名 *称|施設名|事業名|設置場所|橋梁名|投票所|便所名|イベント名|備考,住所|位置|地,緯度,経度' --csv 2>/dev/null
syukaishisetsu,syukaishisetsu-00000001,施設名,住所,緯度,経度
syukaishisetsu,syukaishisetsu-00000002,礫川地域活動センター,東京都文京区小石川2丁目18番18号,35.711995,139.750389
syukaishisetsu,syukaishisetsu-00000003,大原地域活動センター,東京都文京区千石1丁目4番3号,35.724469,139.743379
syukaishisetsu,syukaishisetsu-00000004,大塚地域活動センター,東京都文京区大塚1丁目5番17号,35.718634,139.734637
...
ここで、ヘッダ行そのものは不要であるため削除する。具体的には、opdselect
のコマンドラインオプション--filter
で緯度、経度が実数でないものを取り除く。また、ヘッダ以外にも作成年月日だけの行などデータとしては無意味なものも含まれるため、コマンドラインオプション--strict
で空カラムのある行も取り除く。
root@op:/work/opdutil# dim list -s | cut -d' ' -f 1,3 | opdselect --encoding cp932 --hint '名 *称|施設名|事業名|設置場所|橋梁名|投票所|便所名|イベント名|備考,住所|位置|地,緯度,経度' --filter ',,float,float' --strict --csv 2>/dev/null
syukaishisetsu,syukaishisetsu-00000002,礫川地域活動センター,東京都文京区小石川2丁目18番18号,35.711995,139.750389
syukaishisetsu,syukaishisetsu-00000003,大原地域活動センター,東京都文京区千石1丁目4番3号,35.724469,139.743379
syukaishisetsu,syukaishisetsu-00000004,大塚地域活動センター,東京都文京区大塚1丁目5番17号,35.718634,139.734637
...
StarSeeker用ファイルの生成
最後に、これらの選択されたデータをもとにStarSeeker用のファイルを生成する。
root@op:/work/opdutil# dim list -s | cut -d' ' -f 1,3 | opdselect --encoding cp932 --hint '名 *称|施設名|事業名|設置場所|橋梁名|投票所|便所名|イベント名|備考,住所|位置|地,緯度,経度' --filter ',,float,float' --strict --post-process starseeker --post-process-args base=50000 name=文京区オープンデータ color=white attributes='address:住所,locationName(text):施設名,location(geo:point),time(DateTime)' 2>/dev/null
root@op:/work/opdutil# ls -l *.csv
-rw-r--r-- 1 root root 51 Feb 28 00:30 category.csv
-rw-r--r-- 1 root root 241043 Feb 28 00:30 data.csv
-rw-r--r-- 1 root root 4229 Feb 28 00:30 dataset.csv
StarSeekerへのデータ登録
オープンデータのCSVを作成することができたので、StarSeekerにデータを登録する。
初期状態
いったんStarSeekerの作業ディレクトリに戻り、初期xlsxからcsvを取り出す。このうちtables.csv
だけはそのまま使い、まずはStarSeekerの管理テーブルを作成する。
root@op:/work/opdutil# cd /work
root@op:/work# ./xlsx2csv-all.sh
root@op:/work# ls -l *.csv
-rw-r--r-- 1 root root 140 Feb 28 00:36 category.csv
-rw-r--r-- 1 root root 1637 Feb 28 00:36 point.csv
-rw-r--r-- 1 root root 47319 Feb 28 00:36 point_data.csv
-rw-r--r-- 1 root root 879 Feb 28 00:36 surface.csv
-rw-r--r-- 1 root root 735332 Feb 28 00:37 surface_data.csv
-rw-r--r-- 1 root root 2182 Feb 28 00:37 tables.csv
root@op:/work# cd opdutil
root@op:/work/opdutil# ss_conductor table create ../tables.csv --send $DSN
ここで画面を呼び出すと以下のように地図が表示される。
データセット一覧の作成
文京区のcategory.csv
からPostgresのデータセットカテゴリ定義DMLを生成する。
root@op:/work/opdutil# ss_conductor category create ../tables.csv ./category.csv
insert into t_category (category_id,category_name,category_color,display_order,enabled) values (50000,'文京区オープンデータ','white',10,TRUE);
Postgresにデータセットカテゴリ定義DMLを投入する。なお、環境変数$DSN
はStarSeekerにより自動的に設定されている。
root@op:/work/opdutil# ss_conductor category create ../tables.csv ./category.csv --send $DSN
Postgresのデータセット定義DMLを生成する。
root@op:/work/opdutil# ss_conductor dataset create --name point ../tables.csv ./dataset.csv
insert into t_point_dataset (point_dataset_id,category_id,point_dataset_name,point_color_code,entity_type,coordinates_attr_name,register_time_attr_name,enabled) values (50001,50000,'syukaishisetsu','green','syukaishisetsu','location','time',TRUE);
insert into t_point_detail (point_detail_id,point_dataset_id,item_attr_name,data_type,display_title,display_order,enabled) values (50002,50001,'address',0,'住所',1,TRUE);
insert into t_point_detail (point_detail_id,point_dataset_id,item_attr_name,data_type,display_title,display_order,enabled) values (50003,50001,'locationName',0,'施設名',2,TRUE);
insert into t_point_dataset (point_dataset_id,category_id,point_dataset_name,point_color_code,entity_type,coordinates_attr_name,register_time_attr_name,enabled) values (50024,50000,'zitensyatyusyajo','#7c8869','zitensyatyusyajo','location','time',TRUE);
...
Postgresにデータセット定義DMLを投入する。
root@op:/work/opdutil# ss_conductor dataset create --name point ../tables.csv ./dataset.csv --send $DSN
DML投入後にはデータセット一覧を確認することができる。Orionにデータを投入していないため、データセットを選択してもデータは表示されない。
Orionへのデータ投入
Orionに投入するエンティティJSONを生成する。
root@op:/work/opdutil# ss_conductor data create ../tables.csv ./data.csv
POST {'id': '50004', 'type': 'syukaishisetsu', 'address': {'type': 'text', 'value': '礫川地域活動センター'}, 'locationName': {'type': 'text', 'value': '東京都文京区小石川2丁目18番18号'}, 'location': {'type': 'geo:point', 'value': '35.711995, 139.750389'}, 'time': {'type': 'datetime', 'value': '2022-02-28T00:30:37'}}
POST {'id': '50005', 'type': 'syukaishisetsu', 'address': {'type': 'text', 'value': '大原地域活動センター'}, 'locationName': {'type': 'text', 'value': '東京都文京区千石1丁目4番3号'}, 'location': {'type': 'geo:point', 'value': '35.724469, 139.743379'}, 'time': {'type': 'datetime', 'value': '2022-02-28T00:30:37'}}
POST {'id': '50006', 'type': 'syukaishisetsu', 'address': {'type': 'text', 'value': '大塚地域活動センター'}, 'locationName': {'type': 'text', 'value': '東京都文京区大塚1丁目5番17号'}, 'location': {'type': 'geo:point', 'value': '35.718634, 139.734637'}, 'time': {'type': 'datetime', 'value': '2022-02-28T00:30:37'}}
...
OrionにエンティティJSONを投入する。ここでも環境変数$BROKER
はStarSeeker起動時に自動的に設定されているものを使う。ログの3つ組の意味は、それぞれ、投入したエンティティのID、HTTPレスポンスコード、追加情報である。Orionの場合、HTTPレスポンスコードが201であれば投入に成功している。
root@op:/work/opdutil# ss_conductor data create ../tables.csv ./data.csv --send $BROKER
50004 201 http://orion:1026/v2/entities
50005 201 http://orion:1026/v2/entities
50006 201 http://orion:1026/v2/entities
...
Orionへのエンティティ投入ログを見ると1件だけBadRequest
となっているが、一見すると緯度が異常値のように見える。
50242 400 BadRequest: geo coordinates format error [see Orion user manual]: 35727055, 139.746606 http://orion:1026/v2/entities
ログに出ているIDを参考にopdselect
の出力したファイルであるdata.csv
を確認すると、「hoikuen」(保育園)データセットの「キッズラボ千石園」であることがわかる。
root@op:/work/opdutil# ss_conductor data create ../tables.csv ./data.csv | grep 50242
POST {'id': '50242', 'type': 'hoikuen', 'address': {'type': 'text', 'value': 'キッズラボ千石園'}, 'locationName': {'type': 'text', 'value': '東京都文京区本駒込2丁目9番8号'}, 'location': {'type': 'geo:point', 'value': '35727055, 139.746606'}, 'time': {'type': 'datetime', 'value': '2022-02-28T00:30:37'}}
dim
に戻ってソースCSVを確認すると文京区から取得したデータそのものに間違いがあることが判明した。(文京区さん修正お願いします!)
root@op:/work/opdutil# iconv -f cp932 -t utf-8 <`dim list -s | grep hoikuen | cut -d' ' -f3` | grep キッズラボ千石園
101,キッズラボ千石園,,113-0022,東京都文京区本駒込2丁目9番8号,35727055,139.746606,03-5981-8677,私立保育園,認可保育園,03-5981-8626,76,6,10,12,16,32,,
結果の確認
StarSeekerはOrionからデータを取得して地図に表示することができた。(緊急避難場所を表示している例)
StarSeekerではOrionのポートも公開していおり、直接NGSIでデータを取得することもできる。ただし、素のOrionをインターネットに晒すことは、データの登録・更新もできてしまうことになるため、実際には、Orionの手前にAPI GatewayやReverse Proxyなどを配置し、アプリケーションレイヤーでのアクセス制御を行うことが望ましい。
$ curl -s http://ホスト:1026/v2/entities?limit=5 | jq .
[
{
"id": "50886",
"type": "aedsettikasyoitiran",
"address": {
"type": "text",
"value": "こひなた保育園",
"metadata": {}
},
"location": {
"type": "geo:point",
"value": "35.714013, 139.736125",
"metadata": {}
},
"locationName": {
"type": "text",
"value": "小日向1-21-1",
"metadata": {}
},
"time": {
"type": "datetime",
"value": "2022-02-28T00:30:37",
"metadata": {}
}
},
{
"id": "50887",
"type": "aedsettikasyoitiran",
"address": {
"type": "text",
"value": "駒込保育園",
"metadata": {}
},
"location": {
"type": "geo:point",
"value": "35.729655, 139.76063",
"metadata": {}
},
"locationName": {
"type": "text",
"value": "千駄木3-19-17",
"metadata": {}
},
"time": {
"type": "datetime",
"value": "2022-02-28T00:30:37",
"metadata": {}
}
},
{
"id": "50888",
"type": "aedsettikasyoitiran",
"address": {
"type": "text",
"value": "さしがや保育園",
"metadata": {}
},
"location": {
"type": "geo:point",
"value": "35.718104, 139.749759",
"metadata": {}
},
"locationName": {
"type": "text",
"value": "白山2-32-6",
"metadata": {}
},
"time": {
"type": "datetime",
"value": "2022-02-28T00:30:37",
"metadata": {}
}
},
{
"id": "50918",
"type": "tyosuiso",
"address": {
"type": "text",
"value": "千駄木三丁目第二児童遊園",
"metadata": {}
},
"location": {
"type": "geo:point",
"value": "35.728166, 139.762126",
"metadata": {}
},
"locationName": {
"type": "text",
"value": "千駄木3丁目12",
"metadata": {}
},
"time": {
"type": "datetime",
"value": "2022-02-28T00:30:37",
"metadata": {}
}
},
{
"id": "50919",
"type": "tyosuiso",
"address": {
"type": "text",
"value": "西片二丁目児童遊園",
"metadata": {}
},
"location": {
"type": "geo:point",
"value": "35.716273, 139.756792",
"metadata": {}
},
"locationName": {
"type": "text",
"value": "西片2丁目19",
"metadata": {}
},
"time": {
"type": "datetime",
"value": "2022-02-28T00:30:37",
"metadata": {}
}
}
]
結果と考察
- 文京区オープンデータ(CSV)で緯度、経度情報をもつデータセットを一括して取得し、以下の機能を実装することができた。
- 地図によるデータ公開
- API (NGSI)によるデータ公開
- このままでは以下の課題があり、ひきつづき検討していきたい。
- APIアクセス制御: インターネットとのあいだにAPI Gateway、Reverse Proxyなどをおく
- 住所はあるが緯度、経度のないオープンデータの地図上への表示:たとえばIMI Toolの利用
- データカタログとの連携
- APIカタログとの連携
- データセットごとの全情報の表示
- NGSI PATCH/PUTを容易にするしくみ