「さわって覚える ArcGIS API for Python」シリーズブログは、 ArcGIS API for Python のガイドやサンプル、API リファレンスなどのリソースを最大限ご活用いただく第一歩として、ガイドの中で紹介されている主要なモジュールを中心に、実際にさわって覚えていただくようなノートブックと共に、全 5 回のシリーズとして紹介していく予定です。
前回の記事では、geocode() メソッドを使った、さまざまなジオコーディングについて紹介しました。シリーズ第 4 回目となる今回は、ネットワーク解析編として、「パート1:ネットワーク データセットとネットワーク解析」のノートブックをもとに、ネットワーク解析に必要なコンセプトを説明します。その後、「パート2:ルート検索」と「パート3:到達圏の作成」のノートブックをもとに、主要な処理を解説していきます。
なお、今回はパート2とパート3のノートブックのそれぞれがボリュームが多いので、前編・後編の2回に分けて解説したいと思います。
紹介している翻訳済みのノートブックは、GitHub にも公開しますので、ご参照ください。
ArcGIS API for Python の環境構築がまだお済みでない方は、開発リソース集のインストールガイドにインストール方法を掲載しておりますので、ご参照ください。
本記事では以下の内容でネットワーク解析についてご紹介します。
【ネットワーク解析編(前編)】
・ネットワーク データセットとネットワーク解析
・ネットワーク解析の概要
・ネットワークとは?
・ネットワーク データセット
・ネットワーク解析サービス
・ルート検索
【ネットワーク解析編(後編)】
・到達圏の作成
ArcGIS API for Python の Network Analysis は、次のような質問に答えるために設計されています。
これらの質問は、企業、公共サービス、または組織が業務をより効率的に遂行し、戦略的意思決定を改善することに関連しています。 例えば、組織は自社の商品やサービスにアクセスできる人が分かれば、現在の市場と潜在的な市場の両方をより理解することができます。 時間帯、車両容量、最大移動時間などのいくつかの制約を考慮しながら、停留所を最適に配列し、停留所間の最短経路を見つけることで、輸送コストを削減することができます。 顧客サービスは、より迅速な対応、またはより利便性の高い施設の立地を通じて改善することができます。
以下の図は、ネットワーク解析を利用する一般的なアプリケーションについてまとめたものです。
図 - ネットワーク解析の一般的なアプリケーション
Route(ルート検索)、Closest Facility(最寄りの検索)、Service Area(到達圏)
Vehicle Routing Problem(配車ルート解析)、Location-Allocation(ロケーション・アロケーション)、OD Cost Matrix(OD コストマトリックス)
ネットワークとは、エッジ(ライン)や接続ジャンクション(ポイント)のような要素が相互に接続されたシステムで、ある地点から、別の地点への可能なルートを表します。自動車やトラックは道路を、航空会社は決められた飛行経路を、石油はパイプラインを流れています。潜在的な移動経路をネットワークでモデル化することで、ネットワーク上の石油、トラック、または他のエージェントの移動に関連した分析を行うことができます。最も一般的なネットワーク解析は、2点間の最短経路を見つけることです。
ArcGIS ではネットワークを、ユーティリティ ネットワークとネットワーク データセットの2つのカテゴリに分類していますが、ここで扱うのは、ネットワーク データセットです。
ネットワーク データセットは、道路ネットワークをモデリングするのに適しています。ネットワーク データセットは、シンプル フィーチャ (ラインとポイント) およびターンを含めることができるソース フィーチャから作成され、ソース フィーチャの接続性を格納します。ネットワーク解析を実行するときには、常にネットワーク データセット上で実行されます。
ネットワーク データセットは、ネットワーク エレメントから構成されています。ネットワーク エレメントは、ネットワーク データセットの作成に使用されるソース フィーチャから生成され、接続性の確立には、ソース フィーチャのジオメトリを使用できます。また、ネットワーク エレメントには、ネットワーク上のナビゲーションを制御する属性があります。
ネットワーク エレメントには、次の 3 種類があります:
ネットワークの基本構造はエッジとジャンクションから構成され、ネットワークの接続性はエッジとジャンクションを相互に接続することで確立されます。ターンはオプションのエレメントで、たとえば、ある特定のエッジから別のエッジへの左折を規制する場合など、特定のターン移動に関する情報を格納します。
ネットワーク解析 (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:ルート検索」のノートブックをもとに、主要な処理を解説していきます。
今回の「ルート検索」のノートブックでは、夏のアメリカ合衆国西部の旅行を計画し、マイアミからスタートし、サンフランシスコで旅を終える旅を計画するときの、ルート検索がテーマです。旅の途中でサンノゼ、ロサンゼルス、サンディエゴ、フェニックス、エルパソ、ヒューストン、ニューオーリンズ、オーランドの 8 都市に立ち寄ります。
コードとしては大きく、次に分かれています。
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
Route (ルート検索) | find_routes | plan_routes |
Service Area (到達圏) | generate_service_areas | create_drive_time_areas |
Closest Facility (最寄りの検索) | find_closest_facilities | find_nearest |
これら 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 都市間を移動するための最短ルートを設計して、それらのプロセスの違いを詳細に説明しています。
ルート検索では、複数地点間を移動するための最速または最短の経路を決定することができます。複数のストップを訪問したり、場所間の距離や移動時間を測定したりするために、arcgis.network.analytics モジュールの find_routes ツールを使用することが出来ます。
このツールは実行するたびに1台以上の車両のルートを見つけることができるので、複数のドライバーが事前に指定したストップに移動するための最適なルートを決定することができます。
find_routes のパラメーターは次の通りで、ノートブックでの実行部分のコードは、次の通りです。
[ 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 に格納された結果の確認、テーブルや地図での可視化等については、ノートブックをご参照ください。
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 を実行する場合、
の2つ記載しているように、結果のハンドリングの仕方も異なってきますので、詳細な実行ステップと解説はノートブックをご参照ください。
今回は「ネットワーク解析編(前編)」として、本記事ではネットワーク解析に必要なコンセプトとルート検索で必要なデータの準備と、arcgis.network.analysis.find_routes と arcgis.features.use_proximity.plan_routes をルート解析のツールとして利用するまでの主要なコードと解説を取り上げて紹介しました。
パート 2 のノートブックでは、この記事で取り上げた内容に加え、テーブル形式にする方法、マッピングする方法、そして解析結果を保存する方法についても紹介していますので、より詳しく確認したい方は、ノートブックをご参照ください。
次回は、「ネットワーク解析編(後編)」として、「パート 3 :到達圏の作成」で、network.analysis 及び features.use_proximity モジュールを使った到達圏解析のポイントを紹介する予定です。