スポンサードリンク



こんにちは。sinyです。

本記事ではpythonのライブラリであるOSMnxを使って都市の道路ネットワーク図をJupyterNotebookで可視化する方法についてまとめました。
やり方さえわかれば簡単ですので、興味がある方はぜひ試してみてください。

OSMnxとは?

OSmnxとはOpenStreetMapから道路網の情報を取得して、情報を分析したうえで可視化してくれるパッケージです。

※パッケージの詳細は公式ドキュメントサイトを参照。

環境構築手順

構築手順はいくつかありますが、ここでは一番簡単なcondaを使った手順を紹介します。

まず最初にcondaで仮想環境を作成→アクティベートします。

conda create -n osmnx
activate osmnx

続いて、以下のコマンドでosmnxをインストールします。
※インストール完了まで時間がかかるので気長に待ちましょう。

conda install -c conda-forge osmnx

次にJupyterNotebookをインストールします。

conda install netbook ipykernel

 

JupyterNotebookからconda環境で作った仮想環境を使えるように以下のコマンドを実行します。

ipython kernel install --user --name osmnx


これでJupyter notebookのkernelに作成した仮想環境(osmnx)が追加されます。

jupyter notebookコマンドを実行してJupyterNotebookが起動すればOKです。

以上で環境構築は完了です。

道路ネットワーク図の可視化手順

ここからはJupyterNotebook上でosmnxを使って道路ネットワーク地図を描画します。
例として東京の新宿区の道路ネットワークを描画してみます。

まず最初に必要なモジュールをインポートします。

import networkx as nx
import osmnx as ox
import requests
import sys,os,os.path
import matplotlib.cm as cm
import matplotlib.colors as colors
ox.config(use_cache=True, log_console=True)
ox.__version__

 

次にosmnxのgraph_from_placeメソッドを使って道路ネットワーク情報を取得して地図を描画します。
graph_from_placeメソッドはジオコーディング可能な場所の空間境界内のOSMデータからネットワークグラフを作成します。

place = {'city' : 'Shibuya',
         'state' : 'Tokyo',
         'country' : 'Japan'}
G = ox.graph_from_place(place, network_type='drive')
fig, ax = ox.plot_graph(G, fig_height=12, node_size=0, edge_linewidth=0.5)

 

まずplace変数にcity, state, countryの情報を辞書型データとして格納します。
今回は日本の東京にある新宿区をターゲットにするためcountryはJapan、stateはTokyo、cityにShinjukuを設定します。

次にgraph_from_placeメソッドにplaceとnetwork_typeを指定して地図情報を取得します。
network_type=driveとすると道路ネットワークデータを取得することができます。

実行すると以下のような新宿区の道路ネットワーク図が表示されます。

 

次に同じネットワーク図に色を付けてもう少しいい感じに表示してみます。
処理時間がかなりかかるので気長に待ちましょう。

edge_centrality = nx.closeness_centrality(nx.line_graph(G))
# 元のグラフのエッジ値のリスト
ev = [edge_centrality[edge + (0,)] for edge in G.edges()]

# グラフのエッジの色のリストに変換されたカラースケール
norm = colors.Normalize(vmin=min(ev)*0.8, vmax=max(ev))
cmap = cm.ScalarMappable(norm=norm, cmap=cm.inferno)
ec = [cmap.to_rgba(cl) for cl in ev]

# 元のグラフのエッジを線グラフの近さ中心性で色付けする
fig, ax = ox.plot_graph(G, bgcolor='k', axis_off=True, edge_color=ec, fig_height=12, node_size=0, edge_linewidth=0.5, edge_alpha=1)

 

実行結果は以下のようになりました。

さらに、開始、終了地点の座標を指定して経路を描画してみます。

# 各ポイントに最も近いネットワークノードを取得する
# 新宿近辺の緯度経度を指定
orig_node = ox.get_nearest_node(G, (35.675752, 139.656113 ))
dest_node = ox.get_nearest_node(G, (35.673825, 139.703313 ))


# これらのノード間のルートを見つけてプロットします
route = nx.shortest_path(G, orig_node, dest_node, weight='length')
fig, ax = ox.plot_graph_route(G, route, bgcolor='k', axis_off=True, edge_color=ec, node_size=0, fig_height=12, edge_linewidth=0.5)

 

orig_nodeとdest_nodeに開始と終了地点の緯度経度情報を指定します。
osmnxのshortest_pathメソッドを使って2地点の最短経路を取得します。

route = nx.shortest_path(G, orig_node, dest_node, weight='length')

 

実行結果は以下のようになりました。
最短経路が赤線で描画されます。

2地点点の最短経路の距離(メートル)を表示してみます。

# ルートの距離(メートル)を出力
print("距離は{}メートルです。".format(round(nx.shortest_path_length(G, orig_node, dest_node, weight='length'))))

>> 距離は4938メートルです。

 

次に、ノードに標高を自動的に追加し、エッジグレードを計算してネットワークをプロットしてみます。
これにはOSMNXのadd_node_elevationsメソッドを利用しますが、内部的にGoogle Map Elevationを使うので、別途Maps Elevation APIを有効化してAPIキーを割当てておきましょう。

#from keys import google_elevation_api_key
api_key = '<ここにAPIキーを指定する'
G = ox.add_node_elevations(G, api_key)

G = ox.add_edge_grades(G)
nc = ox.get_node_colors_by_attr(G, 'elevation', cmap='plasma', num_bins=20)
fig, ax = ox.plot_graph(G, fig_height=6, node_color=nc, node_size=12, node_zorder=2, edge_color='#dddddd')

 

以下のように標高で色分けした地図を描画することができます。

最後に新宿駅の1キロ範囲内を取得して地図を描画してみます。

#新宿駅の1キロ範囲内を取得
wurster_hall = (35.689399, 139.703892)
one_mile = 1000 #meters
G = ox.graph_from_point(wurster_hall, distance=one_mile, network_type='drive')
fig, ax = ox.plot_graph(G, fig_height=8, node_size=0)

 

35.689399, 139.703892は新宿駅の緯度経度情報です。
one_mile変数は何メートル圏内を検索するかを定義する変数です。

graph_from_pointメソッドに中心の位置情報とdistanceに検索範囲を指定します。
実行結果は以下のようになりました。

以上、OSmnxの基礎的な利用方法についての紹介でした。

所感としては、地図情報の取得やデータ変換処理にかなり時間がかかるので広範囲を対象にしてデータ検索を実行すると検索結果がなかなか返ってこなくなりちょっと厳しい感じはありました。

あまりリアルタイム性を求めた用途には向いていないと思いますが、地図を絡めた分析結果を可視化するのには便利なパッケージではないかと思います。

ここで紹介した機能以外にもいろんな利用方法があるので、もっと調べて別途記事を書きたいと思います。

 

おすすめの記事