はじめに
「さわって覚える ArcGIS API for Python」シリーズブログは、 ArcGIS API for Python のガイドやサンプル、API リファレンスなどのリソースを最大限ご活用いただく第一歩として、ガイドの中で紹介されている主要なモジュールを中心に、実際にさわって覚えていただくようなノートブックと共にシリーズとして紹介していく予定です。
- 基本編 (GIS モジュール編)
- フィーチャ データ編
- 場所検索、ジオコーディング編
- ネットワーク解析編(前編)/ ネットワーク解析編(後編)
- マッピング、可視化編
- ラスター編
-
前回の記事では、geocode() メソッドを使った、さまざまなジオコーディングについて紹介しました。シリーズ第 4 回目となる今回は、ネットワーク解析編として、「パート1:ネットワーク データセットとネットワーク解析」のノートブックをもとに、ネットワーク解析に必要なコンセプトを説明します。その後、「パート2:ルート検索」と「パート3:到達圏の作成」のノートブックをもとに、主要な処理を解説していきます。
なお、今回はパート2とパート3のノートブックのそれぞれがボリュームが多いので、前編・後編の2回に分けて解説したいと思います。
紹介している翻訳済みのノートブックは、GitHub にも公開しますので、ご参照ください。
ArcGIS API for Python の環境構築がまだお済みでない方は、開発リソース集のインストールガイドにインストール方法を掲載しておりますので、ご参照ください。
本記事では以下の内容でネットワーク解析についてご紹介します。
【ネットワーク解析編(前編)】
・ネットワーク データセットとネットワーク解析
・ネットワーク解析の概要
・ネットワークとは?
・ネットワーク データセット
・ネットワーク解析サービス
・ルート検索
【ネットワーク解析編(後編)】
・到達圏の作成
1. ネットワーク データセットとネットワーク解析
1.1 ネットワーク解析の概要
ArcGIS API for Python の Network Analysis は、次のような質問に答えるために設計されています。
- マンハッタンからブルックリンへの最速の移動手段は?
- サンフランシスコのダウンタウンで火災が発生した場合、車で5分以内に対応できる最寄りの消防署は?
- 各都市の倉庫がカバーしている市場面積は?
- 現在の場所から一番近いコーヒーショップはどこですか?
- 輸送コストを最小限に抑え、顧客サービスを向上させるためには、どのように配送車両のルートを決定すればよいでしょうか?
- 市場シェアを最大化するためには、どこに新しい支店を開設すればよいのでしょうか?
- 当社は縮小する必要があります - 全体的な需要を維持するためには、どの店舗を閉鎖すべきですか?
- 現在または過去の交通状況はどのようなもので、ネットワーク分析の結果にどのように影響しますか?
これらの質問は、企業、公共サービス、または組織が業務をより効率的に遂行し、戦略的意思決定を改善することに関連しています。 例えば、組織は自社の商品やサービスにアクセスできる人が分かれば、現在の市場と潜在的な市場の両方をより理解することができます。 時間帯、車両容量、最大移動時間などのいくつかの制約を考慮しながら、停留所を最適に配列し、停留所間の最短経路を見つけることで、輸送コストを削減することができます。 顧客サービスは、より迅速な対応、またはより利便性の高い施設の立地を通じて改善することができます。
以下の図は、ネットワーク解析を利用する一般的なアプリケーションについてまとめたものです。
図 - ネットワーク解析の一般的なアプリケーション
Route(ルート検索)、Closest Facility(最寄りの検索)、Service Area(到達圏)
Vehicle Routing Problem(配車ルート解析)、Location-Allocation(ロケーション・アロケーション)、OD Cost Matrix(OD コストマトリックス)
1.2 ネットワークとは?
ネットワークとは、エッジ(ライン)や接続ジャンクション(ポイント)のような要素が相互に接続されたシステムで、ある地点から、別の地点への可能なルートを表します。自動車やトラックは道路を、航空会社は決められた飛行経路を、石油はパイプラインを流れています。潜在的な移動経路をネットワークでモデル化することで、ネットワーク上の石油、トラック、または他のエージェントの移動に関連した分析を行うことができます。最も一般的なネットワーク解析は、2点間の最短経路を見つけることです。
ArcGIS ではネットワークを、ユーティリティ ネットワークとネットワーク データセットの2つのカテゴリに分類していますが、ここで扱うのは、ネットワーク データセットです。
1.3 ネットワーク データセット
ネットワーク データセットは、道路ネットワークをモデリングするのに適しています。ネットワーク データセットは、シンプル フィーチャ (ラインとポイント) およびターンを含めることができるソース フィーチャから作成され、ソース フィーチャの接続性を格納します。ネットワーク解析を実行するときには、常にネットワーク データセット上で実行されます。
ネットワーク データセットは、ネットワーク エレメントから構成されています。ネットワーク エレメントは、ネットワーク データセットの作成に使用されるソース フィーチャから生成され、接続性の確立には、ソース フィーチャのジオメトリを使用できます。また、ネットワーク エレメントには、ネットワーク上のナビゲーションを制御する属性があります。
ネットワーク エレメントには、次の 3 種類があります:
- エッジ — 別のエレメント (ジャンクション) に接続するエレメントで、エージェントが移動リンクになります。
- ジャンクション — エッジと接続し、1 つのエッジから別のエッジへのナビゲーションを行います。
- ターン — 複数のエッジの間の移動に影響する可能性のある情報を格納します。
ネットワークの基本構造はエッジとジャンクションから構成され、ネットワークの接続性はエッジとジャンクションを相互に接続することで確立されます。ターンはオプションのエレメントで、たとえば、ある特定のエッジから別のエッジへの左折を規制する場合など、特定のターン移動に関する情報を格納します。
1.4 ネットワーク解析サービス
ネットワーク解析 (NA) サービスは、ArcGIS Network Analysis ソルバ によって呼び出されるようになっています (ルート検索、最寄りの検索、到達圏、ロケーション・アロケーション、ODコストマトリックス、配車ルート解析など)。
ユーザーは、ArcGIS Online でホストされすぐに利用可能なネットワーク解析(NA)サービス、またはユーザーが事前に公開して設定したArcGIS Enterprise 上のカスタマイズされたネットワーク解析(NA)サービスのいずれかを選択することができます。
ArcGIS Online を使用して解析を実行する場合、ソルバ は ArcGIS Online 上に保存されている高品質な世界的な規模のネットワーク データセットを参照し、ArcGIS Online のクレジットを消費します。独自のデータを使用している場合は、Online のクレジットは消費しませんが、ネットワーク データセットをプロジェクトに関連付ける必要があります。
ArcGIS Online ネットワーク解析サービスを使用すると、ネットワーク データセットの作成や購入、ArcGIS Network Analyst エクステンションのライセンス購入をすることなく、過去、現在、および予測される交通状況を表示することもできます(ArcGIS Onlineでの現在、および予想される交通状況のデータは日本地域は未対応です)。これらのサービスは、定期的に更新される高品質の道路データを参照しています。
これらのサービスにアクセスするには、ネットワーク解析の権限を持つ ArcGIS Online の組織向けアカウントが必要であり、アプリケーションが ArcGIS Online に接続している必要があります。また、ArcGIS Online アカウントを使用して ArcGIS Pro のライセンスを取得している場合は、すでにアプリケーションにサインインしている可能性があります。 サービス利用時の消費クレジットについては、次をご参照ください。
表 - ネットワーク解析サービス利用時の消費クレジット。
詳細は弊社ホームページの 機能別のクレジット をご参照ください。
機能 機能(英語) 消費クレジット
到達圏 |
Service Areas |
1 到達圏につき 0.5 クレジット |
最寄りの検索 |
Closest Facility Routes |
1 ルートにつき 0.5 クレジット |
配車ルート解析 |
Multi-Vehicle Routes |
1 ルートにつき 1 クレジット |
ジオエンリッチメント |
GeoEnrichment |
1 変数につき 0.01 クレジット |
単純ルート検索 |
Simple Routes |
1 ルートにつき 0.005 クレジット |
ロケーション・アロケーション |
Location-Allocation |
1 需要地点ルートにつき 0.1 クレジット |
OD コストマトリックス |
Origin Destination Cost Matrix |
1 起点終点ペアにつき 0.0005 クレジット |
ここまでが「パート1:ネットワーク データセットとネットワーク解析」のノートブックの内容をもとに概要を紹介しました。「マルチモーダル ネットワーク データセット」、「3D ネットワーク データセット」などを含め、より詳しい説明はノートブックにありますので、そちらも参照してください。
ここからは、「パート2:ルート検索」のノートブックをもとに、主要な処理を解説していきます。
2. ルートの検索
今回の「ルート検索」のノートブックでは、夏のアメリカ合衆国西部の旅行を計画し、マイアミからスタートし、サンフランシスコで旅を終える旅を計画するときの、ルート検索がテーマです。旅の途中でサンノゼ、ロサンゼルス、サンディエゴ、フェニックス、エルパソ、ヒューストン、ニューオーリンズ、オーランドの 8 都市に立ち寄ります。
コードとしては大きく、次に分かれています。
- データ(入力に使用するデータセットの準備)
- arcgis.network.analysis.find_routes を使ったルート検索
- arcgis.features.use_proximity.plan_routes を使ったルート検索
2.1 データ(入力に使用するデータセットの準備)
find_routes ツールは、ストップ フィーチャ セットを入力パラメーターとして指定する必要があります。フィーチャ セットは、2 つ以上のストップを指定する必要があると同時に、上限は10,000 ストップ、または 1 つのルートに対して 150 ストップです。
詳細な実行ステップと解説はノートブックを参照いただくこととし、既存のフィーチャ サービスからストップを抽出し、フィーチャ セット(FeatureSet)を入力パラメーターとして準備するコードは、次のようになります。
[ データセットの準備のコード ]
from copy import deepcopy
import datetime as dt
from IPython.display import HTML
import json
import pandas as pd
from arcgis.gis import GIS
import arcgis.network as network
import arcgis.geocoding as geocoding
from arcgis.features import FeatureLayer, FeatureSet, FeatureCollection
import arcgis.features.use_proximity as use_proximity
my_gis = GIS(profile="your_online_profile")
# 「USA Major Cities」というタイトルのフィーチャ レイヤーにsearch メソッドでアクセス
sample_cities = my_gis.content.search('title:"USA Major Cities" type:Feature Service owner:esri*',
outside_org=True)[0]
# 訪問する都市をリストに配置、整形用のフォーマッタを定義
stops_cities = ['San Francisco', 'San Jose', 'Los Angeles', 'San Diego',
'Phoenix', 'El Paso',
'Houston', 'New Orleans', 'Orlando', 'Miami']
values = "'" + "', '".join(stops_cities) + "'"
stops_cities_fl = FeatureLayer(sample_cities.url + "/0")
# FeatureLayer のquery メソッドを呼び出し、各都市をFeatureSet として取得
stops_cities_fset = stops_cities_fl.query(where="ST in ('CA', 'NV', 'TX', 'AZ', 'LA', 'FL') AND NAME IN ({0})".format(values), as_df=False)
# 同様に、旅の出発点のマイアミをFeatureSet として取得
start_cities_fset = stops_cities_fl.query(where="ST='FL' AND NAME = 'Miami'", as_df=False)
""" 任意の順序にストップを並べ替える関数を定義
"""
def re_order_stop_cities(fset=stops_cities_fset, start_city = "Miami", end_city = "San Francisco"):
stops_cities_flist = []
last_city = None
for ea in fset:
if ea.attributes['NAME'] == start_city:
stops_cities_flist.insert(0, ea)
elif ea.attributes['NAME'] == end_city:
last_city = ea
else:
stops_cities_flist.append(ea)
stops_cities_flist.append(last_city)
return FeatureSet(stops_cities_flist)
# FeatureSet 内のストップを、旅の開始地点と終着点が正しくなるように並べ替え
re_ordered_stops_cities_fset = re_order_stop_cities()
# 並べ替えた FeatureSet に spatialReference を定義
re_ordered_stops_cities_fset.spatial_reference = stops_cities_fset.spatial_reference
# メソッド2で後から使用
re_ordered_stops_cities = list(map(lambda x: x.attributes['NAME'], re_ordered_stops_cities_fset))
ここからが、「ルート検索」のノートブックで最も理解していただきたい
ポイント なので、本記事でも取り上げます。
ArcGIS API for Python はルート解析の方法として、RouteLayer.solve、find_routes、plan_routes の 3つのメソッドを提供しています。
解析の種類 network.analysis features.use_proximity
これら 3 つのメソッドは異なるモジュールで定義されており、裏側では異なる REST API を呼び出しています。RouteLayer.solve と network.analysis.find_routes、features.use_proximity.plan_routes の主な違いは、RouteLayer.solve は独自もしくは高度なネットワーク解析のワークフローを想定しており、独自のネットワーク解析レイヤーを公開する必要があります。
network.analysis.find_routes、features.use_proximity.plan_routes は、ArcGIS Online 上でホストされているルート検索 サービスに対して動作し、プロキシ サービスを介して ArcGIS Enterprise 上で利用することもできます。利用にはクレジット消費が必要となります。
今回は、同一の問題を network.analysis.find_routes() と features.use_proximity.plan_routes() で解析し、それらのワークフローについて stops_cities で定義された 10 都市間を移動するための最短ルートを設計して、それらのプロセスの違いを詳細に説明しています。
2.2 arcgis.network.analysis.find_routes を使ったルート検索
ルート検索では、複数地点間を移動するための最速または最短の経路を決定することができます。複数のストップを訪問したり、場所間の距離や移動時間を測定したりするために、arcgis.network.analytics モジュールの find_routes ツールを使用することが出来ます。
このツールは実行するたびに1台以上の車両のルートを見つけることができるので、複数のドライバーが事前に指定したストップに移動するための最適なルートを決定することができます。
find_routes のパラメーターは次の通りで、ノートブックでの実行部分のコードは、次の通りです。
- stops: 必須パラメーター。2つ以上のストップを指定します。
- preserve_terminal_stops: ターミナル ストップを維持 (str 型)。任意パラメーター。 最適なルートを見つけるためreorder_stops_to_find パラメーターが True の場合、スタートまたは終了する地点を保存できます。そしてツールは残りのストップを並べ替えます。
- time_of_day: 時刻 (datetime 型)。任意パラメーター。ルートの移動を開始する時間と日付を指定。
- time_zone_for_time_of_day: 時刻のタイム ゾーン (str 型)。任意パラメーター。
- time_of_day:パラメーターのタイム ゾーンを指定します。
- もしアウトプットのルートを新しいレイヤー ファイルに保存したい場合、save_output_na_layer を True に設定します。
[ find_routes 実行部分のコード ]
start_time = int(dt.datetime.now().timestamp() * 1000)
result = network.analysis.find_routes(re_ordered_stops_cities_fset, time_of_day=start_time,
time_zone_for_time_of_day="UTC",
preserve_terminal_stops="Preserve None",
reorder_stops_to_find_optimal_routes=True,
save_output_na_layer=True)
result に格納された結果の確認、テーブルや地図での可視化等については、ノートブックをご参照ください。
2.3 arcgis.features.use_proximity.plan_routes 使ったルート検索
plan_routes メソッドは、移動するワーカーに対してタスクを効率的に配分する方法を決定します。ストップと利用できる車両の数を含むインプットを入力すると、ツールが各ストップを車両に割り当て、各車両が割り当てられたストップに最短時間で到着するルートを返却します。plan_routes を使うことで、現地作業者よりたくさんの作業現場に少ない時間で到達することができます。これにより生産性が向上し、カスタマー サービスを改善することができます。組織はしばしば plan_routes を次のような目的のために使用します。
- 住宅、レストラン、建設現場の点検
- 修理、設置、技術サービスの提供
- 商品や小包の配送
- 営業電話をかける
- 観客の自宅からイベントまでのバンでの移動手段の提供
plan_routes メソッドの詳細は API リファレンスをご参照ください。
ノートブックでの実行部分のコードは、output_name の指定の有無により、次の通り異なります。
[ plan_routes 実行部分のコード ]
# 入力パラメータの準備
re_ordered_values = "'" + "', '".join(re_ordered_stops_cities) + "'"
# それぞれレイヤー
stops_layer = {'url': sample_cities.layers[0].url,
'filter': "ST in ('CA', 'NV', 'TX', 'AZ', 'LA', 'FL') AND NAME IN ({0})".format(re_ordered_values)}
start_layer = {'url': sample_cities.layers[0].url,
'filter': "ST = 'FL' AND NAME = 'Miami'"}
end_layer = {'url': sample_cities.layers[0].url,
'filter': "NAME = 'San Francisco'"}
# output_nameを指定した場合
""" using https://analysis7.arcgis.com/arcgis/rest/services/tasks/GPServer/PlanRoutes/submitJob
"""
result1 = use_proximity.plan_routes(stops_layer=stops_layer, route_count=1,
max_stops_per_route=10, route_start_time=start_time,
start_layer_route_id_field = "FID",
start_layer=start_layer,
end_layer=end_layer,
travel_mode='運転時間',
return_to_start=False,
context={'outSR': {"wkid": 4326}},
output_name="Plan Route from Miami to San Francisco 2a",
gis=my_gis)
result1 に格納された結果の確認や地図での可視化等については、ノートブックをご参照ください。
# output_nameを指定しない場合
""" using https://analysis7.arcgis.com/arcgis/rest/services/tasks/GPServer/PlanRoutes/submitJob
"""
result1 = use_proximity.plan_routes(stops_layer=stops_layer, route_count=1,
max_stops_per_route=10, route_start_time=start_time,
start_layer_route_id_field = "FID",
start_layer=start_layer,
end_layer=end_layer,
travel_mode='運転時間',
return_to_start=False,
context={'outSR': {"wkid": 4326}},
gis=my_gis)
result1 に格納された結果の確認や地図での可視化等については、ノートブックをご参照ください。
また、arcgis.features.use_proximity.plan_routes を実行する場合、
- output_name を指定する場合:解析結果を直接フィーチャ サービスとして出力することが可能です。
- output_name を指定しない場合:解析結果が FeatureCollection で返却されるため、結果の可視化にはパース / 描画というアプローチを取る必要があります。
の2つ記載しているように、結果のハンドリングの仕方も異なってきますので、詳細な実行ステップと解説はノートブックをご参照ください。
おわりに
今回は「ネットワーク解析編(前編)」として、本記事ではネットワーク解析に必要なコンセプトとルート検索で必要なデータの準備と、arcgis.network.analysis.find_routes と arcgis.features.use_proximity.plan_routes をルート解析のツールとして利用するまでの主要なコードと解説を取り上げて紹介しました。
パート 2 のノートブックでは、この記事で取り上げた内容に加え、テーブル形式にする方法、マッピングする方法、そして解析結果を保存する方法についても紹介していますので、より詳しく確認したい方は、ノートブックをご参照ください。
次回は、「ネットワーク解析編(後編)」として、「パート 3 :到達圏の作成」で、network.analysis 及び features.use_proximity モジュールを使った到達圏解析のポイントを紹介する予定です。
関連リンク
- ArcGIS 関連ページ
- シリーズブログ 関連ページ
- 開発リソース集
- 関連するノートブック
- 関連資料