catalinaの備忘録

ソフトウェアやハードウェアの備忘録。後で逆引きできるように。

GISデータの分析入門

かたりぃなです。今回はデータ分析の練習として、GISデータの分析を試してみたいと思います。

出典:国土交通省国土数値情報ダウンロードサイトhttps://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-S12-v2_7.html

利用規約はこちら https://nlftp.mlit.go.jp/ksj/other/agreement.html#agree-02

データの分析にはpythonのpandasを使ってみます。

GISデータとは

https://www.mlit.go.jp/kokudoseisaku/gis/guidance/guidance_1.html

にあるように、地理情報システムの略です。 GISソフトというのを使うことで、地図上にデータを重畳して可視化することができるものです。

提供されているデータを見てみると

  • 洪水浸水想定区域
  • 地価公示
  • 行政区域
  • 駅別乗降客数

など、色々と面白いことができそうです。実データで遊ぶシムシティといったところでしょうか。

しかし、触れたことのないデータを使って可視化という高度なことは難しそうです。 まずはデータをざっと触ってみてどんな感じかを見ていきたいとおもいます。

  • 駅別乗降客数

を使って簡単なグラフを出してみたり、仮説を立てて分析するなどを試みたいと思います。

このデータを選んだ理由は私が鉄道が好きだからというのと、身近なデータのほうが理解しやすいという2点からです。

今回の目的はデータ分析なので、興味ある分野のほうが勉強も捗ると思いますし、身近なものであればデータそのものを理解する手間がかからずに良いと思います。

とりあえずファイルを読み込むコツ

pandasのread_jsonで読んでみるも、ダメでした。

import pandas as pd
df = pd.read_json("./S12-18_GML/S12-18_NumberOfPassengers.geojson")

これでうまくいかない理由は

{
"type": "FeatureCollection",
"features": [

のようなtop階層がついてるため、全てのデータがfeaturesのコレクションとして扱われてしまうためです。

今回はこういった形で読み込むことでうまくいきました。

import pandas as pd
import json
with open('./S12-18_GML/S12-18_NumberOfPassengers.geojson') as f:
    data = json.load(f)
    df = pd.json_normalize(data["features"])

# うまく読み込めたので一旦保存しておく
df.to_csv("work.csv")

一旦pythonの標準機能でファイルを読み込んでjsonデコードしたうえで、featuresノード以下のみ使うことを明示します。 pandasのjson_normalizeでこれを平坦にしてから使います。 (この記事をひととおり書き終わってからgeojsonを扱う専用パッケージがあるらしいことを知ったので、別途試したいと思います。)

やっと分析開始

まずは直観的にわかりやすいものを見ていくことにします。

目標:西武新宿線の駅ごとの乗降客数(2014年)をグラフにする

なんでこの路線を選択したかというと、単に私が昔利用していた路線なので。

実際の利用者視点と実データとの剥離はあるとは思いますが、直観的にこうなるだろうなという予測は立ちますし、分析結果がだいたいあってるかどうかくらいは判断がつきそうという理由です。

データの仕様はこちら https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-S12-v2_7.html

必要なデータを抽出する

まずは元になるgeojsonデータとその仕様をざっと眺めてみます。 運営会社と路線名一覧で絞り込みたいので、それぞれの列を軽く見てみると次のことがわかります。

  • 路線名について
  • 駅データについて
    • 複数路線が乗り入れている駅が複数記載されている場合がある
    • 「xx鉄道、yy線を含む」などの記載があるので、集計時に注意が必要そう

それぞれの問題について検討します。

路線名について他の路線もざっと眺めてみると 「4号線丸ノ内線」や「8号線有楽町線」「12号線大江戸線」などが見受けられます。 これはおそらく鉄道要覧(https://ja.wikipedia.org/wiki/%E9%89%84%E9%81%93%E8%A6%81%E8%A6%A7) に登録されている名称でこのデータを作ったためと思われます。

少々わかりにくいですが、今回の分析の対象とする西武新宿線は会社名と路線名で抽出できそうです。 「西武鉄道」の「新宿線」ですね。

西武鉄道新宿線は直通乗り入れ先が存在していない単純な路線なので扱いやすそうです。(運行上のダイヤでは拝島線と一体化していますが、駅データとしては別モノのようです。)

ただ、直通乗り入れこそないものの、乗り換え可能駅はあるため、集計時に注意をしたほうがよさそうです。

特に所沢のような複数路線が乗り入れる駅のカウントがどうなるのかという問題があります。

乗換駅での乗降客数のデータといえば、たとえばダンジョンで有名な渋谷の乗降客数を見てみると次のようになります。

>>> df[(df['properties.S12_001']=="渋谷")][['properties.S12_002','properties.S12_003','properties.S12_021']]
      properties.S12_002 properties.S12_003  properties.S12_021
612                 京王電鉄               井の頭線              336805
6070              東京急行電鉄              田園都市線                   0
6105              東京急行電鉄                東横線             1108543
6173               東京地下鉄             3号線銀座線              212534
6303               東京地下鉄           11号線半蔵門線                   0
6952             東日本旅客鉄道                山手線              757078
10128              東京地下鉄           13号線副都心線                   0

あれほど大きな駅にもかかわらずゼロという数字が3つもあり、これがおかしいことは直感的に理解できるかと思います。

乗降客数データ以外にもデータ有無フラグ, 重複フラグ, 備考があるので出してみます。

>>> df[(df['properties.S12_001']=="渋谷")][['properties.S12_002','properties.S12_003','properties.S12_021', 'properties.S12_018', 'properties.S12_019', 'properties.S12_020']]
      properties.S12_002 properties.S12_003  properties.S12_021  properties.S12_018  properties.S12_019                      properties.S12_020
612                 京王電鉄               井の頭線              336805                   1                   1                                     NaN
6070              東京急行電鉄              田園都市線                   0                   2                   1                                     NaN
6105              東京急行電鉄                東横線             1108543                   1                   1  田園都市線、東京地下鉄、11号線半蔵門線・東京地下鉄、13号線副都心線を含む
6173               東京地下鉄             3号線銀座線              212534                   1                   1                                     NaN
6303               東京地下鉄           11号線半蔵門線                   0                   2                   1                                     NaN
6952             東日本旅客鉄道                山手線              757078                   1                   1                                     NaN
10128              東京地下鉄           13号線副都心線                   0                   2                   1                                     NaN

0の路線にもデータは存在しており、重複フラグに2が設定されています。「他路線駅に記載」とのことです。

重複フラグの仕様:https://nlftp.mlit.go.jp/ksj/gml/codelist/RailwayDuplicateCd.html)

田園都市線、東京地下鉄、11号線半蔵門線・東京地下鉄、13号線副都心線を含むとのことなので、これらの路線は東横線の乗降客数としてカウントされているようです。

鉄道好きのポエム

該当路線で渋谷駅を利用した方であれば分かると思いますが、上記で東横線としてカウントされている路線はすべて改札内乗り換えが可能な路線です。 逆に地下鉄銀座線は半蔵門線と同じ運営会社であるにもかかわらず、改札内乗り換えはできません。

推測ではありますが、おそらく改札の入退場者数をカウントしているのではないかなと思われます。

ちなみに東急の渋谷駅は共同使用駅(https://ja.wikipedia.org/wiki/%E5%85%B1%E5%90%8C%E4%BD%BF%E7%94%A8%E9%A7%85)であるので、他路線の共同使用駅でも同様の傾向がありそうです。

たとえば小田急線の厚木駅のデータでも同様の記載があります。

>>> df[(df['properties.S12_001']=="厚木")][['properties.S12_002','properties.S12_003','properties.S12_021', 'properties.S12_018', 'properties.S12_019', 'properties.S12_020']]
     properties.S12_002 properties.S12_003  properties.S12_021  properties.S12_018  properties.S12_019 properties.S12_020
3062              小田急電鉄               小田原線               20745                   1                   1     東日本旅客鉄道、相模線を含む
7445            東日本旅客鉄道                相模線                   0                   2                   1                NaN

必要なデータの抽出

というわけで、まずは抽出からです。 対話モードで確認しつつ進めます。

# 会社一覧
df['properties.S12_002'].unique()

# 路線名一覧
df['properties.S12_003'].unique()

# 運営会社「西武鉄道」で抽出
# df[df['properties.S12_002'].str.contains("西武")] 部分一致で良いならこうする
df[df['properties.S12_002']=="西武鉄道"]    # 完全一致

# 路線名「新宿線」で抽出
# df[df['properties.S12_003'].str.contains("新宿線")] 部分一致で良いならこうする
df[df['properties.S12_003']=="新宿線"]    # 完全一致

# 西武新宿線の行すべて
# df[(df['properties.S12_002'].str.contains("西武")) & (df['properties.S12_003'].str.contains("新宿線")) ] 部分一致版
ss = df[(df['properties.S12_002']=="西武鉄道") & (df['properties.S12_003']=="新宿線")]

# 保存
ss.to_csv('ss.csv')

これで西武新宿線の全29駅の乗降客数のデータを抽出できました。

分析の前準備

データの仕様として次のような記載があるので、見てみます。

乗降客数2014
(S12_021)   2014年の駅別乗降客数(人/日)

2014というと、ちょうど10年前のデータですね。

駅別の乗降客数を出してみましょう。

>>> ss = pd.read_csv('ss.csv')
>>> ss[['properties.S12_001', 'properties.S12_021']]
   properties.S12_001  properties.S12_021
~~略~~
19                本川越               48880
20                新狭山               21171
21                新所沢               54698
22                 所沢                   0
23                久米川               31761
24                武蔵関               28792
~~略~~

ゼロ人ということは考えづらいので、詳しく見てみます。

所沢は西武池袋線との乗換駅なので、ゼロになっている可能性がありそうです。 前述の渋谷駅同様に調べてみます。

# 所沢駅を探す
>>> df[(df['properties.S12_001']=="所沢")][['properties.S12_002','properties.S12_003','properties.S12_021', 'properties.S12_018', 'properties.S12_019', 'properties.S12_020']]
     properties.S12_002 properties.S12_003  properties.S12_021  properties.S12_018  properties.S12_019 properties.S12_020
4813               西武鉄道                新宿線                   0                   2                   1                NaN
4873               西武鉄道                池袋線               95772                   1                   1                NaN

備考欄の記載がありませんが、重複フラグが2で、データ有無フラグが1なので有効なデータであり、それは他路線に記載されているとのことです。

所沢駅は1つしかない(西武の池袋線新宿線)ので、西武池袋線所沢駅の乗降客数を参照すればよさそうです。

(※必要に応じて路線の重みを考えて適切に分割する必要がありそうですが、今回はそのまま使います。)

ss(西武新宿線の略)として新しくデータフレームを切り出してあるので、元データは変更せずに切り出したデータ側を修正することにします。

ss = pd.read_csv('ss.csv')
ss.at[22, 'properties.S12_021'] = df.at[4873, 'properties.S12_021']

確認

>>> ss[['properties.S12_001', 'properties.S12_003', 'properties.S12_021']]
     properties.S12_001 properties.S12_003  properties.S12_021
~~略~~
21                新所沢                新宿線               54698
22                 所沢                新宿線               95772
23                久米川                新宿線               31761

よさそうです。補正したデータを保存しておきましょう。

ss.to_csv("ss.csv")

プロット

いよいよプロットです。プロットする前に。 日本語そのままではうまく表示できないので、対処します。

日本語対応パッケージをインストールして

pip install japanize-matplotlib

プロットするだけ

import matplotlib.pyplot as plt
import japanize_matplotlib
ss.plot.bar('properties.S12_001', 'properties.S12_021')
plt.savefig("test.png")

でOKです。

properties.S12_001は駅名で、properties.S12_021は2014年度の乗降客数です。

これで、各駅ごとの乗降客数の棒グラフが出せました。 駅名が少し見切れていますが、一旦見るぶんには充分でしょう。

各駅の乗降客数と次のことがいえそうです。

  • 高田馬場, 西武新宿の乗降客数が圧倒的に多い
  • 次点で所沢、田無が多い
  • 他の駅はグラフのスケールに対して乗降客数が少ないため、視認ではうまく比較できない

です。

この路線を利用したことがある人は「知ってた」って感じの結果かと思います。

並び順を制御する

鉄道というものは駅という複数の点を線で結んだ交通手段です。

今回の練習用に採用した西武新宿線の路線には枝線は存在しておらず、1つの線で表現されます。

住居を選ぶ際には「都心へのアクセスの良さ」などが一つの指標としてあげられますが、単純に都心から遠くなるほど利用者が減るという予想は立ちそうです。

つまり分析の観点からは「都心からの距離順でデータを見てみたい」となります。鉄道の用語でいう「営業キロ」順に並べて分析したいというものです。

今回のデータには営業キロは付随していないので、wikipediaから拾ってくることにします。 29件くらいなら手入力できるレベルなのでやっつけちゃいます。 https://ja.wikipedia.org/wiki/%E8%A5%BF%E6%AD%A6%E6%96%B0%E5%AE%BF%E7%B7%9A

転記して以下のようにしてやっつけてしまいたいです。

distance = [0, 2.0, 3.2, 3.9, 5.2, 6.1, 7.1, 8, 8.5, 9.8, 10.7, 11.7, 12.8, 14.1, 15.3, 16.3, 17.6, 19.9, 22.6, 24.6, 26, 28.9, 30.5, 31.7, 35.6, 38.6, 41.3, 43.9, 47.5]
ss['distance'] = distance

が、駅別の乗降客数データがソートされていないためうまくいきません。 キーとなる駅名をも入力して、それを使ってマージするのが良いでしょう。

wikipediaの情報をもとにこういった形のcsvを作って駅名で結合を試しました。

station,distance
西武新宿,0.0
高田馬場,2.0
下落合,3.2
中井,3.9
~~ 略 ~~
import pandas as pd
d = pd.read_csv("distance.csv")
ss = pd.read_csv("ss.csv")
ss2 = pd.merge(ss, d, on='properties.S12_001')  # 駅名で結合

# 一旦これで保存しておく
ss2.to_csv("ss2.csv")

結合できました。 ソートしてからプロットしてみましょう。

import matplotlib.pyplot as plt
import japanize_matplotlib

ss2=pd.read_csv("ss2.csv")

# 営業キロでソート
sorted_ss2 = ss2.sort_values('distance')
#sorted_ss2 = ss2.sort_values('distance', ascending=False)

sorted_ss2.plot.bar('properties.S12_001', 'properties.S12_021')
plt.savefig("test.png")

良い感じになりました。 駅を順に並べてプロットしたグラフからは新しい気付きがあります。

  • 始発駅から遠くなるほど乗降客数が一定数減るわけではなく、山がある。
  • 田無より先の区間の乗降客数は、田無までと比較してまんべんなく多い(都心部ほど利用者が多いという決めつけはよくない)

ここから先の詳細分析は手間がかかりそうなので、別の機会にやりたいと思います。

私の気が向いたときに分析できるように、因子と思われるものだけ列挙しておきます。急行停車駅,乗換駅,幹線道路,移動方向などが影響していると思われます。

利用者数が多い駅(グラフで山になっていた駅)と、田無から先の傾向それぞれ、

  • 利用者数が若干多い駅
  • 傾向の変化
    • 田無より先 - ここから先は各駅停車と有料特急のみ
    • 東村山より先 - このあたりから路線は東西から南北に切り替わる

鉄道好きのポエム2

田無から先や東村山より先といった用語でピンときた人もいるかもしれません。

このようなデータの変化がみられる要因は西武鉄道の成り立ちによる影響も大きいと考えます。

大雑把にいうと、国分寺~川越間で始まったのが西武鉄道のご先祖様です。この路線に接続するように東村山ー高田馬場で開業し、今の西武新宿線の形ができたという流れです。

地理情報をもとに駅間距離を算出する

先ほどはwikipediaから路線の営業キロ数を拾ってきましたが、 地理情報をもとに始発駅からの距離順にソートすることもできそうです。

厳密な営業キロ数は算出できませんが、簡易的な始発駅からの距離順ソートで充分なこともあるかと思います。

地理情報に深入りすると大変なことになりそうなので、要点だけ抽出します。 https://www.gsi.go.jp/GIS/jpgis/download/docs200703/JPGIS10_2007-03_kaisetsu.pdf のドキュメントを「GM_Curve」で検索すると、なるほど?といった感じの情報が幾つかひっかかります。

地理データのドキュメントと照らし合わせてみると、駅の位置情報はgeometry.coordinatesに含まれていて、「線」で表現されるようです。

たとえば始発駅である西武新宿駅の座標情報はこのように定義されています。

"geometry": { "type": "LineString", "coordinates": [ [ 139.70004, 35.6953 ], [ 139.70004, 35.69605 ], [ 139.70012, 35.69704 ] ] }

駅の座標を確認する

googleマップで座標が合っているか見てみます。 googleマップで検索する場合は、このデータの北緯と東経の順序を入れ替えて「35.6953, 139.70004」として検索すると、該当座標が表示されます。

3つの値はそれぞれ西武新宿駅

  • 南口付近
  • 駅の中央付近
  • ホームの北端付近

を示しているので、だいたいあっていそうです。 今回は始発駅からの距離を使って順序付けしたいだけなので、 ss2['geometry.coordinates.0'][n] で駅座標の1つめの点を使って差分を求めます。

import pandas as pd
import json

# 駅名
ss['properties.S12_001']

# 駅名指定で座標を抽出(始発駅である'西武新宿'を指定)
terminal = ss[ss['properties.S12_001'] == '西武新宿'].iloc[0]

# 駅の座標(複数あるうちの最初の座標を使うことにする)。
# なぜか文字列型で格納されているのでjsonデコードする
base_point = json.loads(terminal['geometry.coordinates'])[0]

# 始発駅からの直線距離を求める関数
import math
def calc_distance(point_str):
    p = json.loads(point_str)[0]
    x = p[0] - base_point[0]
    y = p[1] - base_point[1]
    return math.hypot(x, y)

# すべての駅について始発駅からの直線距離を求める
ss['distance'] = ss['geometry.coordinates'].map(calc_distance)

# 一旦保存
ss.to_csv("ss_with_distance.csv")

あとはソートしてプロットするだけ。

import matplotlib.pyplot as plt
import japanize_matplotlib

ss=pd.read_csv("ss_with_distance.csv")

# 距離順にソート
sorted_ss = ss.sort_values('distance')

sorted_ss.plot.bar('properties.S12_001', 'properties.S12_021')
plt.savefig("test.png")

同じグラフが出ました。ただし曲がりくねっている路線や環状線ではこの方法では問題が起きると思いますので、別の方法を考える必要があるでしょう。 (もしかしたら路線データもあったりするかもしれませんね。)

練習

他路線や他年度も同様にグラフ化できます。 基本的なことは同じなので、これまでの操作がそのまま使えます。

たとえば小田急小田原線を使う場合はこのように。

import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
import json

# 2点間の距離を求める
import math
def calc_distance(point_str):
    p = json.loads(point_str)[0]
    x = p[0] - base_point[0]
    y = p[1] - base_point[1]
    return math.hypot(x, y)

# データを読み込む
df = pd.read_csv('work.csv')

# 小田急小田原線を抽出
oh = df[(df['properties.S12_002']=="小田急電鉄") & (df['properties.S12_003']=="小田原線")].copy()

# 始発駅の適当な座標を抽出する
terminal = oh[oh['properties.S12_001'] == '新宿'].iloc[0]
base_point = json.loads(terminal['geometry.coordinates'])[0]

# 始発駅からの直線距離を求める
oh['distance'] = oh['geometry.coordinates'].map(calc_distance)

# 距離順にソート
sorted_oh = oh.sort_values('distance')

# プロット
sorted_oh.plot.bar('properties.S12_001', 'properties.S12_021', figsize=(10, 8))
plt.savefig("test.png")

こんな感じのものができました。

修正点

1点だけ変更点があって、

oh = df[(df['properties.S12_002']=="小田急電鉄") & (df['properties.S12_003']=="小田原線")].copy()

の箇所で明示的にdataframeをcopyしています。 これは、この箇所でこういったエラーが出ることに対する対処となります。

<stdin>:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

まだ詳しく理解できていませんが、dataframeを操作して得たdataframeはviewとcopyの2種類があって、暗黙的に生成されたcopyに対して代入を行うとこの警告が出るようです。 今回は元データを変更したいわけではないので、copyで明示的に複製することで解決しています。

ちなみに、最初に西武新宿線で実験していた時に問題が起きなかったのは、一旦csvに保存してそこから作業していたためです。

小田急線の分析

グラフの傾向としては、西武新宿線に近いものがありそうですが、幾つか異なる点も見受けられます

  • 単純に駅数が多い
  • 始発駅から遠くなるほど乗降客数が一定数減るわけではなく、山がある。
  • 利用者数が西武新宿線より圧倒的に大きい
  • 都心部では新宿・代々木上原の利用者数が多く、郊外では登戸・町田の利用者が多い

それぞれについて軽く考えます。

駅が多いのは輸送距離が長いためと考えられます。 小田急小田原線西武新宿線の2倍近い距離をもつ路線ですので、これが影響しているのかもしれませんね。それに伴って利用者数にも差がでている可能性も考えられます。

利用者の多い山は急行停車駅です。これは西武新宿線と同様の傾向ですね。

次に利用者数が多い理由については今回のデータだけから読み取るのは難しいです。 すぐ思いつくものとして、複々線が考えられます。

代々木上原~登戸間は複々線となっていて線路容量が2倍なので、単純計算するなら2倍の人を運べると考えられます。

都心と郊外それぞれの利用者が多い駅について、これらはすべて乗換駅です。 特に登戸は南武線、町田は横浜線との乗り換え駅であるため、それらの路線から乗り換える人が多いのではないかと考えられます。

小田急線データの補正

グラフを見ると相模大野駅が2つあって、一方の乗降客数がゼロです。

詳細を見ると相模大野として4つの駅が登録されているようです。 乗降客数のデータを拾うだけであればインデックス3048に入っている126479を使えばよさそうです。

2路線しか乗り入れていない駅にもかかわらず4つもデータがあるのは少々不思議ですね。 ジオメトリを見ると値に違いがありそうですが、データの仕様などを詳しく見てみないことにはなんともいえないので、今回はこのくらいにしておきます。

>>> df[(df['properties.S12_001']=="相模大野")][['properties.S12_002','properties.S12_003','properties.S12_021', 'properties.S12_018', 'properties.S12_019', 'properties.S12_020', 'geometry.coordinates']]
     properties.S12_002 properties.S12_003  properties.S12_021  properties.S12_018  properties.S12_019 properties.S12_020                            geometry.coordinates
3007              小田急電鉄               江ノ島線                   0                   2                   1                NaN  [[139.43698, 35.53111], [139.43774, 35.53215]]
3011              小田急電鉄               江ノ島線                   0                   2                   1                NaN  [[139.43679, 35.53119], [139.43774, 35.53215]]
3048              小田急電鉄               小田原線              126479                   1                   1                NaN  [[139.43879, 35.53329], [139.43774, 35.53215]]
3072              小田急電鉄               小田原線                   0                   2                   1                NaN  [[139.43679, 35.53119], [139.43774, 35.53215]]

練習2

色々と分析しやすいよう、スクリプト化してみました。

以下の内容をanalyze.pyとして保存し、python analyze.py 西武鉄道 新宿線 西武新宿 2014のようにして実行できます。 実行すると

でグラフが生成されます。

エラーチェックはしていないので、存在しない路線などを指定するとエラーになってしまいます。 このあたりは追々考えていきたいところです。

import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
import json
import sys

# memo: usage
# python analyze.py 運営会社名 路線名 始発駅名 年度
# 
# examples.
# python analyze.py 小田急電鉄 小田原線 新宿 2014
# python analyze.py 西武鉄道 新宿線 西武新宿 2014 
#
company = sys.argv[1]
line_name = sys.argv[2]
termilan_name = sys.argv[3]
year = sys.argv[4]
print(int(year))

year2key = {2011: 'S12_009', 2012: 'S12_013', 2013: 'S12_017', 2014: 'S12_021', 2015: 'S12_025', 2016: 'S12_029', 2017: 'S12_033'}

# 年をキーに置き換える
key = year2key[int(year)]

# 2点間の距離を求める
import math
def calc_distance(point_str):
    p = json.loads(point_str)[0]
    x = p[0] - base_point[0]
    y = p[1] - base_point[1]
    return math.hypot(x, y)

# データを読み込む
df = pd.read_csv('work.csv')

# 会社と路線で抽出
railway = df[(df['properties.S12_002']==company) & (df['properties.S12_003']==line_name)].copy()

# 始発駅の適当な座標を抽出する
terminal = railway[railway['properties.S12_001'] == termilan_name].iloc[0]
base_point = json.loads(terminal['geometry.coordinates'])[0]

# 始発駅からの直線距離を求める
railway['distance'] = railway['geometry.coordinates'].map(calc_distance)

# 距離順にソート
sorted_oh = railway.sort_values('distance')

# プロット
sorted_oh.plot.bar('properties.S12_001', 'properties.'+key, figsize=(10, 8))
filename = company+'-'+line_name+'-'+year+'.png'
plt.savefig(filename)

感想と今後の展望

データ分析の基礎的な部分として、注目するデータを抽出してグラフにすることができました。 Pandasは初めてだったのですが、大昔にR言語でやっていた時と似たような感覚で使えることがわかりました。

一旦スクリプトとしてまとめましたが、これでいいのかという疑問があるため、次回は利便性を含めて考えていきたいと思います。

例えば

  • 特定の年だけでなく、年別で利用者数の増減を比較したい
  • 他路線との比較による傾向分析
  • 急行停車駅や道路情報・人口密度など、他の情報も含めた分析

などが考えられます。

スクリプトとしてどこまでやるかという問題に関しても、Excel上で試行錯誤したいこともあると思うので、路線単位で切り出しまでに留めて置くのも一つの方法かもしれません。

それでは今回はこれくらいで。