diff --git a/ViewGTFS.html b/ViewGTFS.html index a028326..c9263fc 100755 --- a/ViewGTFS.html +++ b/ViewGTFS.html @@ -1502,22 +1502,27 @@

GTFSをDuckDBに読み込む

-
$ duckdb viweGTFS.duckdb
+
$ duckdb ViewGTFS.duckdb
 
 v1.0.0 1f98600c2c
 Enter ".help" for usage hints.
 D 
    +
  • Spartial Spartial Extensionを有効にする(2回目以降はLOAD spatialのみで使える)
  • +
+
INSTALL spatial;
+LOAD spatial;
+
  • stops.txt、shapes.txt, trips.txtを直接クエリし、その結果をテーブルとして保存
-
-- stops.csvをstopsテーブルに保存する
-CREATE OR REPLACE TABLE stops AS SELECT * FROM read_csv('stops.txt');
-CREATE OR REPLACE TABLE shapes AS SELECT * FROM read_csv('shapes.txt');
-CREATE OR REPLACE TABLE trips AS SELECT * FROM read_csv('trips.txt');
+
-- stops.csvをstopsテーブルに保存する
+CREATE OR REPLACE TABLE stops AS SELECT * FROM read_csv('stops.txt');
+CREATE OR REPLACE TABLE shapes AS SELECT * FROM read_csv('shapes.txt');
+CREATE OR REPLACE TABLE trips AS SELECT * FROM read_csv('trips.txt');
  • 作成したテーブルを確認してみる
-
SELECT * FROM stops LIMIT 5;
+
SELECT * FROM stops LIMIT 5;
@@ -1630,50 +1635,50 @@

例外: stop_times.txtの対応

  • 殆どはスキーマ自動推論に任せれば大丈夫だが、stop_times.txtだけ時刻が25:00:00などの日付を超えた表記方法が出現しtime型で読み込もうとして失敗するので、Schema(Columns)指定する
-
CREATE OR REPLACE TABLE stop_times AS SELECT * FROM read_csv(
-    'stop_times.txt', 
-    header=true, 
-    columns={ 
-        'trip_id': 'VARCHAR', 
-        'arrival_time': 'VARCHAR', 
-        'departure_time': 'VARCHAR', 
-        'stop_id': 'VARCHAR', 
-        'stop_sequence': 'INTEGER', 
-        'stop_headsign': 'VARCHAR', 
-        'pickup_type': 'UTINYINT', 
-        'drop_off_type': 'UTINYINT', 
-        'shape_dist_traveled': 'DOUBLE', 
-        'timepoint': 'UTINYINT' 
-});
+
CREATE OR REPLACE TABLE stop_times AS SELECT * FROM read_csv(
+    'stop_times.txt', 
+    header=true, 
+    columns={ 
+        'trip_id': 'VARCHAR', 
+        'arrival_time': 'VARCHAR', 
+        'departure_time': 'VARCHAR', 
+        'stop_id': 'VARCHAR', 
+        'stop_sequence': 'INTEGER', 
+        'stop_headsign': 'VARCHAR', 
+        'pickup_type': 'UTINYINT', 
+        'drop_off_type': 'UTINYINT', 
+        'shape_dist_traveled': 'DOUBLE', 
+        'timepoint': 'UTINYINT' 
+});

蛇足: GTFSをDuckDBに変換する

面倒なので、GTFSをダウンロードしてDuckDBにロードするbashスクリプトを書いた

-
# Usage: bash GTFS2DuckDB.sh GTFS_URL
-# bash GTFS2DuckDB.sh https://api-public.odpt.org/api/v4/files/Toei/data/ToeiBus-GTFS.zip
-
-TITLE=$1
-GTFS_URL=$2
-
-GTFS_FILE=${GTFS_URL##*/}
-
-# GTFSファイルをダウンロード
-echo "Download: $GTFS_FILE"
-curl -L -o $TITLE.zip $GTFS_URL
-
-echo "Import: $GTFS_FILE to $TITLE.duckdb"
-for basename in `unzip -Z1 $TITLE.zip`; do
-    filename=${basename%.*}
-    echo "${filename} to DuckDB"
-    # stop_timesのみスキーマ自動判定が失敗するので、手動でスキーマ定義を渡す(arrival_time, departure_timeが25:00:00のような24時越えの値を含むため)
-    if [ $filename = "stop_times" ]; then
-        unzip -p $TITLE.zip $basename | duckdb $TITLE.duckdb -c "CREATE OR REPLACE TABLE ${filename} AS SELECT * FROM read_csv('/dev/stdin', header=true, columns={ 'trip_id': 'VARCHAR', 'arrival_time': 'VARCHAR', 'departure_time': 'VARCHAR', 'stop_id': 'VARCHAR', 'stop_sequence': 'INTEGER', 'stop_headsign': 'VARCHAR', 'pickup_type': 'UTINYINT', 'drop_off_type': 'UTINYINT', 'shape_dist_traveled': 'DOUBLE', 'timepoint': 'UTINYINT' })"
-    else
-        unzip -p $TITLE.zip $basename | duckdb $TITLE.duckdb -c "CREATE OR REPLACE TABLE ${filename} AS SELECT * FROM read_csv('/dev/stdin')"
-    fi
-done
+
# Usage: bash GTFS2DuckDB.sh GTFS_URL
+# bash GTFS2DuckDB.sh https://api-public.odpt.org/api/v4/files/Toei/data/ToeiBus-GTFS.zip
+
+TITLE=$1
+GTFS_URL=$2
+
+GTFS_FILE=${GTFS_URL##*/}
+
+# GTFSファイルをダウンロード
+echo "Download: $GTFS_FILE"
+curl -L -o $TITLE.zip $GTFS_URL
+
+echo "Import: $GTFS_FILE to $TITLE.duckdb"
+for basename in `unzip -Z1 $TITLE.zip`; do
+    filename=${basename%.*}
+    echo "${filename} to DuckDB"
+    # stop_timesのみスキーマ自動判定が失敗するので、手動でスキーマ定義を渡す(arrival_time, departure_timeが25:00:00のような24時越えの値を含むため)
+    if [ $filename = "stop_times" ]; then
+        unzip -p $TITLE.zip $basename | duckdb $TITLE.duckdb -c "CREATE OR REPLACE TABLE ${filename} AS SELECT * FROM read_csv('/dev/stdin', header=true, columns={ 'trip_id': 'VARCHAR', 'arrival_time': 'VARCHAR', 'departure_time': 'VARCHAR', 'stop_id': 'VARCHAR', 'stop_sequence': 'INTEGER', 'stop_headsign': 'VARCHAR', 'pickup_type': 'UTINYINT', 'drop_off_type': 'UTINYINT', 'shape_dist_traveled': 'DOUBLE', 'timepoint': 'UTINYINT' })"
+    else
+        unzip -p $TITLE.zip $basename | duckdb $TITLE.duckdb -c "CREATE OR REPLACE TABLE ${filename} AS SELECT * FROM read_csv('/dev/stdin')"
+    fi
+done

GTFSのURLを指定したら、ダウンロードしてDuckDBに読み込んで保存する(e.g. /ToeiBus-GTFS.zip を指定したら、ToeiBus-GTFS.duckdbとして保存する)

-
bash GTFS2DuckDB.sh https://api-public.odpt.org/api/v4/files/Toei/data/ToeiBus-GTFS.zip
+
bash GTFS2DuckDB.sh https://api-public.odpt.org/api/v4/files/Toei/data/ToeiBus-GTFS.zip
@@ -1683,27 +1688,27 @@

Kepler.glで可視化する

DuckDBでGTFSをKepler.glで可視化できるデータに変換する

-
%%sql
--- stopsをCSVで出力する
-COPY (
-    SELECT * FROM stops
-) TO 'ToeiBus-GTFS_stops.csv' WITH (FORMAT CSV, HEADER);
-
-
%%sql
--- shapesから運行路線形状をGeoJSON::LineStringで出力する
+-- stopsをCSVで出力する
 COPY (
-    SELECT * FROM trips
-    LEFT JOIN (
-        SELECT 
-            shape_id,
-            {
-                "type": 'LineString',
-                "coordinates": list([shape_pt_lon,shape_pt_lat])
-            }::JSON AS "geometry" 
-        FROM shapes GROUP BY shape_id
-    ) AS shapes ON trips.shape_id = shapes.shape_id
-) TO 'ToeiBus-GTFS_trips.csv' WITH (FORMAT CSV, HEADER);
+ SELECT * FROM stops +) TO 'ToeiBus-GTFS_stops.csv' WITH (FORMAT CSV, HEADER);
+ +
+
%%sql
+-- shapesから運行路線形状をGeoJSON::LineStringで出力する
+COPY (
+    SELECT * FROM trips
+    LEFT JOIN (
+        SELECT 
+            shape_id,
+            {
+                "type": 'LineString',
+                "coordinates": list([shape_pt_lon,shape_pt_lat])
+            }::JSON AS "geometry" 
+        FROM shapes GROUP BY shape_id
+    ) AS shapes ON trips.shape_id = shapes.shape_id
+) TO 'ToeiBus-GTFS_trips.csv' WITH (FORMAT CSV, HEADER);
@@ -1750,12 +1755,12 @@

国勢調査と組み合わせてみる

  • ダウンロードしてきたファイルを解凍し、DuckDBに読み込む
  • -
    $ unzip QDDSWQ5339.zip
    -$ duckdb viweGTFS.duckdb
    -v1.0.0 1f98600c2c
    -Enter ".help" for usage hints.
    -D load spatial;
    -D CREATE OR REPLACE TABLE mesh_5th AS SELECT * FROM ST_Read('MESH05339.shp');
    +
    $ unzip QDDSWQ5339.zip
    +$ duckdb ViewGTFS.duckdb
    +v1.0.0 1f98600c2c
    +Enter ".help" for usage hints.
    +D load spatial;
    +D CREATE OR REPLACE TABLE mesh_5th AS SELECT * FROM ST_Read('MESH05339.shp');
    @@ -1763,24 +1768,24 @@

    国勢調査と組み合わせてみる

  • 東京都が含まれるM5339の5次メッシュ国勢調査結果データをダウンロードする
  • ダウンロードしてきたファイルを解凍し、文字コードをCP932(ShiftJIS)からUTF-8に変換する(しなくてもなんとかなるが、なんとなく気持ち悪いので変換する)
  • -
    $ unzip -p tblT001142Q5339.zip | iconv -c -f cp932 -t utf-8 > tblT001142Q5339_utf8.txt
    +
    $ unzip -p tblT001142Q5339.zip | iconv -c -f cp932 -t utf-8 > tblT001142Q5339_utf8.txt
    -
    $ duckdb viweGTFS.duckdb
    -v1.0.0 1f98600c2c
    -Enter ".help" for usage hints.
    -D load spatial;
    --- 2行の日本語ヘッダーがレコードとして含まれているが気にしない
    -D CREATE OR REPLACE TABLE census AS SELECT * FROM read_csv('tblT001142Q5339_utf8.txt', header = true);
    +
    $ duckdb ViewGTFS.duckdb
    +v1.0.0 1f98600c2c
    +Enter ".help" for usage hints.
    +D load spatial;
    +-- 2行の日本語ヘッダーがレコードとして含まれているが気にしない
    +D CREATE OR REPLACE TABLE census AS SELECT * FROM read_csv('tblT001142Q5339_utf8.txt', header = true);
    -
    -- メッシュ内総人口はT001142001カラムに保存されているので、メッシュコードのポリゴンと人口をJOINしてGeoJSONとして保存する
    -D COPY (
    -    SELECT mesh_5th.KEY_CODE, census.T001142001 AS population, geom FROM mesh_5th 
    -    LEFT JOIN census ON mesh_5th.KEY_CODE = census.KEY_CODE
    -) TO 'census.geojson' WITH (FORMAT GDAL, DRIVER 'GeoJSON', LAYER_CREATION_OPTIONS 'WRITE_BBOX=YES');
    +
    -- メッシュ内総人口はT001142001カラムに保存されているので、メッシュコードのポリゴンと人口をJOINしてGeoJSONとして保存する
    +D COPY (
    +    SELECT mesh_5th.KEY_CODE, census.T001142001 AS population, geom FROM mesh_5th 
    +    LEFT JOIN census ON mesh_5th.KEY_CODE = census.KEY_CODE
    +) TO 'census.geojson' WITH (FORMAT GDAL, DRIVER 'GeoJSON', LAYER_CREATION_OPTIONS 'WRITE_BBOX=YES');
    diff --git a/ViewGTFS.ipynb b/ViewGTFS.ipynb index 0b4efb1..43c395c 100755 --- a/ViewGTFS.ipynb +++ b/ViewGTFS.ipynb @@ -373,13 +373,20 @@ "## GTFSをDuckDBに読み込む\n", "- DuckDBを起動する\n", "```bash\n", - "$ duckdb viweGTFS.duckdb\n", + "$ duckdb ViewGTFS.duckdb\n", "\n", "v1.0.0 1f98600c2c\n", "Enter \".help\" for usage hints.\n", "D \n", "```\n", "\n", + "- Spartial Spartial Extensionを有効にする(2回目以降はLOAD spatialのみで使える)\n", + "```sql\n", + "INSTALL spatial;\n", + "LOAD spatial;\n", + "```\n", + "\n", + "\n", "- stops.txt、shapes.txt, trips.txtを直接クエリし、その結果をテーブルとして保存\n", "```sql\n", "-- stops.csvをstopsテーブルに保存する\n", @@ -722,7 +729,7 @@ "- ダウンロードしてきたファイルを解凍し、DuckDBに読み込む\n", "```bash\n", "$ unzip QDDSWQ5339.zip\n", - "$ duckdb viweGTFS.duckdb\n", + "$ duckdb ViewGTFS.duckdb\n", "v1.0.0 1f98600c2c\n", "Enter \".help\" for usage hints.\n", "D load spatial;\n", @@ -738,7 +745,7 @@ "```\n", "- 変換したデータをDuckDBに読み込む\n", "```bash\n", - "$ duckdb viweGTFS.duckdb\n", + "$ duckdb ViewGTFS.duckdb\n", "v1.0.0 1f98600c2c\n", "Enter \".help\" for usage hints.\n", "D load spatial;\n",