library(sf)
library(tidyverse)
library(tmap)
library(tmaptools)
library(sfnetworks)
library(tidygraph)国土数値情報 道路データとRを活用したネットワーク解析~津波避難困難地域の分析~
本ドキュメントは、クリエイティブ・コモンズ・ライセンス表示4.0国際(CC BY 4.0)ライセンスのもとで提供されています(クリエイティブ・コモンズ・ライセンスについては、下記のサイトを参照してください)。 クリエイティブ・コモンズ・ライセンス表示4.0国際
本ドキュメントは下記の著作物をもとに改変して作成しています: 国土交通省 政策統括官付 地理空間情報課「国土数値情報 道路データとQGISを活用したネットワーク解析~津波避難困難地域の分析~」(2026年3月) https://nlftp.mlit.go.jp/ksj/manual/QGIS_manual_05.htm (CC BY 4.0)
はじめに
この記事では、主に防災・危機管理、都市計画・まちづくりに関わる方を対象に、国土数値情報 道路データとRを活用した指定緊急避難場所からのネットワーク解析(到達圏解析)によって、津波の避難困難地域を分析する方法を紹介します。
到達圏解析
指定緊急避難場所を起点に、道路ネットワーク上で一定距離(例:500 m)以内に到達できる範囲を算出します。
到達圏解析結果に凸包などの処理を適用し、到達圏を「面」として把握しやすい形に整えます。
人口分布や津波浸水想定エリアとの重ね合わせ
- 250 mメッシュ別将来推計人口データや、津波浸水想定データを到達圏解析結果に重ね合わせます。
これらの分析により、避難困難地域の有無を把握し、避難場所の立地の評価や、今後の対策検討などに活用できる基礎資料を作成します。
また、この記事では、和歌山県すさみ町を対象地域として分析を行います。 すさみ町では、南海トラフ地震を見据え、「フェーズフリー(平時と災害時の区別なく活用できる考え方)」をビジョンとしたスマートシティ構想を推進し、さまざまな実証実験が行われています (PLATEAUを活用したドローン航路作成とデジタル避難訓練(すさみ町役場地域未来課))。
- この記事は、Rの基本操作ができることを前提として書かれています。
道路データとは
国土数値情報 道路データは、道路法に基づく高速自動車国道、一般国道、都道府県道、市区町村道など全国の道路について、道路中心線の形状データと、道路分類や幅員区分などの属性情報を整備したGISデータです。 平成7年(1995年)版のデータ以来、長らく更新されていませんでしたが、この度、約30年ぶりに更新データを公開しました(データ基準年:令和6年度(2024年度)版)。
国土数値情報 道路データは、ノード・リンク構造は持たないラインデータであるものの、GISソフトの機能を用いた簡易的な距離計測や到達圏解析などのネットワーク解析には十分活用することができます。 また、道路種別や幅員区分の違いを踏まえた道路の可視化・分析にも活用することができます。

道路データのダウンロードと読み込み
国土数値情報から道路データをダウンロードし、Rに読み込みます。
国土数値情報の「道路データのダウンロードページ」にアクセスします。 ページをスクロールすると、ダウンロード対象地域を選択できる地図が表示されます。 目的のエリアのメッシュを選択し、[ダウンロード]ボタンをクリックします。
本記事では、すさみ町が含まれるメッシュ番号5035のデータをダウンロードし、以降の説明を行います。

画面上に「国土数値情報ダウンロードサイト ユーザーアンケート」が表示されます。 必要に応じて回答し、回答を完了するか[スキップする]をクリックすると、データのダウンロードが開始されます。

データのダウンロードが完了したら、ZIPファイルを解凍して、「.geojson」ファイルをdataフォルダに追加しましょう。
以降では、ワーキングディレクトリにdataという名前のデータフォルダがあり、使用するファイルはすべてdataフォルダに入っているものとします。
ダウンロードしたデータを、Rに読み込んで表示してみましょう。
ここで、背景地図として地理院地図などを追加しておくとよいでしょう。 ここでは、地理院地図(淡色)を追加しています。
road <- read_sf("data/N13-24_5035.geojson")
gsi_tile <- "https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png"
credit <- "国土数値情報および地理院タイル(淡色地図)を加工して作成"
tm_shape(road) + tm_lines(col = "red") +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
ここで、背景地図として地理院地図などを追加しておくとよいでしょう。ここでは、地理院地図(淡色)を追加しています。
属性テーブルの確認
続いて、道路データの属性テーブルを確認します。
glimpse(road)Rows: 125,541
Columns: 9
$ N13_001 <date> 2017-04-03, 2017-04-03, 2017-04-03, 2024-04-24, 2024-04-24, …
$ N13_002 <chr> "3", "3", "3", "1", "1", "1", "1", "1", "1", "1", "1", "1", "…
$ N13_003 <chr> "3", "3", "3", "3", "3", "3", "1", "1", "1", "3", "3", "3", "…
$ N13_004 <chr> "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "…
$ N13_005 <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ N13_006 <chr> "1", "1", "1", "2", "1", "2", "3", "3", "3", "1", "1", "1", "…
$ N13_007 <chr> "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "…
$ N13_008 <chr> "503514", "503514", "503514", "503515", "503515", "503515", "…
$ geometry <LINESTRING [°]> LINESTRING (135.5925 33.498..., LINESTRING (135.59…
道路データの属性テーブルを確認すると、国道や都道府県道などの道路分類を示す「N13_003」や、道路の幅員を示す「N13_006」など、さまざまな情報が格納されていることが分かります。
幅員区分属性によるスタイリング
幅員区分の属性(N13_006)に応じた色分け表示を行ってみます。
road_width <-
c("3m未満", "3m-5.5m未満", "5.5m-13m未満", "13m-19.5m未満", "19.5m以上", "不明")
road <- road |>
mutate(N13_006 = factor(N13_006, levels = 1:6, labels = road_width))
tm_shape(road) + tm_lines(col = "N13_006") +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
道路データの前処理
ここからは、道路データを到達圏解析で使用するための前処理を行います。 具体的には、対象市町村(すさみ町)のポリゴンでデータを切り抜き、正確な距離計算ができるよう平面直角座標系に投影変換し、指定緊急避難場所を津波対応のものに絞り込みます。
行政区域データから対象市町村のみ抽出
道路データは1次メッシュ単位で整備されており、比較的広い範囲をカバーしています。 今回は和歌山県すさみ町を対象に分析を行うため、すさみ町の行政区域データを使って道路データを切り出します。
国土数値情報から和歌山県の「行政区域データ」をダウンロードします。
ダウンロードが完了したらZIPファイルを解凍し、「.geojson」ファイルをdataフォルダに追加しましょう。
region <- st_read("data/N03-20250101_30.geojson")Reading layer `N03-20250101_30' from data source
`/Users/kzktmr/Documents/ksj_manual/data/N03-20250101_30.geojson'
using driver `GeoJSON'
Simple feature collection with 4106 features and 6 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: 134.9985 ymin: 33.4326 xmax: 136.0135 ymax: 34.38448
Geodetic CRS: JGD2011
tm_shape(region) + tm_polygons() +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
次に、和歌山県の行政区域を「すさみ町」のみに絞り込みます。
属性データを見ると、「N03_004」に市区町村名が格納されていることがわかります。
glimpse(region)Rows: 4,106
Columns: 7
$ N03_001 <chr> "和歌山県", "和歌山県", "和歌山県", "和歌山県", "和歌山県", "和歌山県", "和歌山県", "和歌山県…
$ N03_002 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ N03_003 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ N03_004 <chr> "所属未定地", "和歌山市", "和歌山市", "和歌山市", "和歌山市", "和歌山市", "和歌山市", "和歌山…
$ N03_005 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ N03_007 <chr> "30000", "30201", "30201", "30201", "30201", "30201", "30201"…
$ geometry <POLYGON [°]> POLYGON ((135.9618 33.60632..., POLYGON ((135.256 34.…
filter関数を使って、「市区町村(N03_004)」が「すさみ町」のレコードのみを抽出します。
susami <- region |> filter(N03_004 == "すさみ町")
tm_shape(susami) + tm_polygons() +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
道路データを市町村の範囲で切り取る
次に、st_filter関数を使って、道路データをすさみ町ポリゴンで切り抜きます。
susami_road <- road |> st_filter(susami)
tm_shape(susami_road) + tm_lines(col = "N13_006") +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
道路データを平面直角座標系に投影変換
ここまでで、すさみ町の道路データのみを抽出できました。 到達圏解析では正確な距離計算が必要なため、メートル単位で扱える座標系(平面直角座標系)に変換します。
なお、平面直角座標系についての詳細は、国土地理院の「わかりやすい平面直角座標系」をご覧ください。
susami_road <- susami_road |> st_transform(6674)どの地域でどの系を利用するのかは「平面直角座標系(平成十四年国土交通省告示第九号)」として定められています。 和歌山県は平面直角座標系VI系ですので、そのEPSGコードである「6674」をst_transform関数の引数に与えています。
指定緊急避難場所データの追加と抽出
データの追加
到達圏解析の起点となる指定緊急避難場所のデータを追加します。 本記事では、国土地理院が公開する「指定緊急避難場所データ」を活用します。
ダウンロードページにアクセスして、分析対象地域である和歌山県の指定緊急避難場所データをダウンロードしましょう。 ダウンロードしたZIPデータを解凍し、GeoJSONファイルをdataフォルダに追加します。 追加したらRに読み込みましょう。
shelter <- st_read("data/30000_2.geojson") |>
st_transform(st_crs(susami))Reading layer `30000_和歌山県' from data source
`/Users/kzktmr/Documents/ksj_manual/data/30000_2.geojson' using driver `GeoJSON'
Simple feature collection with 2611 features and 14 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: 135.0681 ymin: 33.43756 xmax: 136.0036 ymax: 34.36827
Geodetic CRS: WGS 84
空間的なデータ処理を行うために、他のデータとCRSを合わせています。
津波に対応した施設を抽出
指定緊急避難場所は、災害の危険から命を守るために緊急的に避難する場所です。 例えば大地震が発生し、津波の到達が予想される場合は、津波災害に対応している指定緊急避難場所へ避難することになります。
避難所データの属性テーブルを確認すると、災害の種類ごとに、指定緊急避難場所に該当する場合「1」に、該当しない場合「““」となるような属性が設定されていることがわかります。
glimpse(shelter)Rows: 2,611
Columns: 15
$ NO <chr> "1", "2", "3", "4", "5", "6", "7", "8", "9", "…
$ 共通ID <chr> "E3034100001201", "E3034100002201", "E30341000…
$ 施設.場所名 <chr> "移レストハウス", "天野地域交流センター(ゆずり葉)", "久木コミュニティセンター",…
$ 住所 <chr> "和歌山県かつらぎ町大字移82-1", "和歌山県かつらぎ町大字下天野930", "和歌山県…
$ 洪水 <chr> "1", "1", "1", "1", "1", "1", "1", "1", "1", "…
$ 崖崩れ.土石流及び地滑り <chr> "1", "1", "", "", "", "", "", "", "", "1", "1"…
$ 高潮 <chr> "", "", "", "", "", "", "", "", "", "", "", ""…
$ 地震 <chr> "1", "1", "", "", "", "1", "", "1", "1", "1", …
$ 津波 <chr> "", "", "", "", "", "", "", "", "", "", "", ""…
$ 大規模な火事 <chr> "", "", "", "", "", "", "", "1", "", "", "", "…
$ 内水氾濫 <chr> "1", "1", "1", "1", "1", "1", "1", "1", "1", "…
$ 火山現象 <chr> "", "", "", "", "", "", "", "", "", "", "", ""…
$ 指定避難所との住所同一 <chr> "1", "1", "1", "1", "1", "1", "1", "1", "1", "…
$ 備考 <chr> "", "", "", "", "", "", "", "", "", "", "", ""…
$ geometry <POINT [°]> POINT (135.4555 34.29469), POINT (135.51…
ここでは、指定緊急避難場所のうち、津波に対応している施設(「津波」属性が「1」)のみをフィルタで抽出します。
先ほどと同様に、filter関数を適用します。 同時に、すさみ町の避難場所だけを抽出するために、st_filter関数を使っています。
shelter <- shelter |>
filter(`津波` == "1") |>
st_filter(susami)津波を対象とする指定緊急避難場所のみが抽出されました。
tm_shape(shelter) + tm_symbols(size = 0.1) +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
到達圏解析の実施
到達圏解析とは、「道路ネットワーク上において、ある地点から一定の距離(または時間)以内に到達できる範囲」を算出する空間解析です。 Rでは、sfnetworkおよびtidygraphというネットワーク分析のパッケージを利用することで、到達圏解析の機能を実現することができます。
本記事では、津波対応の指定緊急避難場所を起点とした到達圏を作成し、人口メッシュを重ねることで、「人口が一定数あるにもかかわらず、近くに避難場所がない」可能性のある場所を可視化します。
なお、「津波避難対策推進マニュアル検討会報告書(消防庁、H25.3)」において、避難可能な限界距離として 500m程度を目安とすることが示されています。そのため、本記事ではこの基準に基づき、避難場所から500m以内を到達圏として解析を実施します(実務においては、分析対象地域の状況に合わせて距離の設定を調整してください)。
指定緊急避難場所からの到達圏
まずは、as_sfnetwork関数を使って、道路網データをsfnetwork形式に変換します。 この時、ネットワークがいくつかの成分(コンポーネント)に分かれるのですが、ここではそのうち最大の成分だけを使うことにします。
network <- susami_road |>
as_sfnetwork(directed = FALSE) |> # 無向グラフに変換
activate("nodes") |>
mutate(component = group_components()) |>
filter(component == 1) # 最大成分を抽出次に、避難場所データを道路網データに統合します。 まず、避難場所データを投影変換して道路網データのCRSと合わせます。
そしてst_network_blend関数を使って、避難場所のポイントデータを道路網データに「ブレンド」します。 これは、道路網の中で、各避難場所に最も近い地点を探し出し、 必要に応じてその場所に新たにノードを挿入する操作です。 これによって、道路網上で各避難場所最も近い場所からの距離を計算することが可能になります。
そして、道路網上で各避難場所に相当するノード(の番号)を、shelter_nodesに格納しておきます。
shelter <- shelter |> st_transform(6674)
network <- network |> st_network_blend(shelter) Warning: st_network_blend assumes attributes are constant over geometries
shelter_nodes <- network |>
activate("nodes") |>
mutate(node_id = row_number()) |> # ノード番号として行番号を設定
filter(!is.na(`共通ID`)) |> # 避難場所のノードだけを抽出
pull(node_id) # ノード番号を取り出す道路網上の最短距離を計算するために、エッジごとにその長さを設定しておく必要があります。 ここでは、edge_length関数を使って、全てのエッジの長さを計算しています。
network <- network |>
activate("edges") |>
mutate(length = edge_length())1つの避難場所から、一定の距離で到達可能なノードを見つけ、それらのポリゴンを作成する関数make_polygonを定義しています。 この関数の中では、node_distance_from関数を使って、あるノードから全てのノードまでの距離を計算しています。 そして閾値となる距離によって一定距離以下のノードだけを抽出し、 (そのノード数が3個以上である場合に限って)st_convex_hull関数を使ってそれらノードからなる道路網の凸包を計算しています。
service_area <- function(i, threshold = 500){
# nodes <-
network |>
activate("nodes") |>
mutate(distance = node_distance_from(i, weights = length)) |>
filter(distance <= threshold) |>
st_as_sf("edges")
# if(nrow(st_as_sf(nodes)) < 3)return(NULL)
# nodes |> st_as_sf() |> st_union() |> st_convex_hull() |> st_as_sf()
}それでは、全ての避難場所に対してmake_polygon関数を適用します。
shelter_area <-
shelter_nodes |> map(service_area) |>
list_rbind() |> st_as_sf()結果を地図にしてみましょう。 道路ネットワーク上で500 m以内に到達できる範囲の道路データが出力されていることが分かります。
tm_shape(shelter_area) + tm_lines(col = "green") +
tm_shape(shelter) + tm_symbols(size = 0.1) +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
凸包で到達圏ポリゴンの作成
結果は「到達できる道路線」として出力されるため、そのままだと面としての広がりや空白が直感的に把握しにくい状態です。 そこでst_convex_hull関数を使って「凸包」処理を行い、面データに変換します。
shelter_polygon <-
shelter_nodes |> map(service_area) |>
map(st_union) |> map(st_convex_hull) |> map(st_as_sf) |>
list_rbind() |> st_as_sf()
tm_shape(shelter_polygon) + tm_polygons(fill = "green") +
tm_shape(shelter) + tm_symbols(size = 0.1) +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
それぞれの指定緊急避難場所からの到達圏ポリゴンが作成できましたが、避難場所が密集しているエリアでは、複数のポリゴンが重なって見づらくなっています。 そこで、st_union関数を使って、全てのポリゴンを1つに融合します。
shelter_polygon <- shelter_polygon |>
st_union() |> st_as_sf()
tm_shape(shelter_polygon) + tm_polygons(fill = "green") +
tm_shape(shelter) + tm_symbols(size = 0.1) +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
人口メッシュ・津波浸水想定エリアとの重ね合わせ
国土数値情報の「250 mメッシュ別将来推計人口データ」を到達圏解析結果に重ね合わせます。
population <- read_sf("data/250m_mesh_2024_30.geojson") |>
filter(SHICODE == "30406")
tm_shape(population) +
tm_polygons(
fill = "PTN_2025",
fill.scale = tm_scale_intervals(values = "brewer.reds")
) +
tm_shape(shelter_polygon) +
tm_polygons(col = "red", fill = NULL) +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
すさみ町全域を俯瞰すると、津波対応の指定緊急避難場所から500 m以内の到達圏について、山間部の一部メッシュは含まれていないものの、沿岸部においては大部分のメッシュが含まれていることが分かります。
次に、詳細を確認するため、すさみ町役場周辺のエリアを見てみます。 メッシュのラベルには、「2025年の総数人口(PTN_2025)」の値を表示しています。
tm_shape(
population,
bbox = bb(URLencode("すさみ町"), width = 0.05, height = 0.025)
) +
tm_polygons(
fill = "PTN_2025",
fill.scale = tm_scale_intervals(values = "brewer.reds")
) +
tm_text(text = "PTN_2025", size = 0.3) +
tm_shape(shelter_polygon) +
tm_polygons(col = "red", fill = NULL, lwd = 2) +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
津波対応の指定緊急避難場所から500m以内の到達圏は、人口の存在するメッシュを概ねカバーしており、避難所配置が全体として一定程度機能していることが確認できます。
なお、本記事で示した結果はあくまで道路ネットワークと距離に基づく簡易的な解析であり、実際の避難における様々な要因を完全には反映していない点にご留意ください。 実際の検討にあたっては、地形条件、避難経路の安全性、地域の実情など、多角的な視点からの総合的な判断が必要となります。
最後に、国土数値情報から「津波浸水想定データ」を重ねてみます。
hazard <- c(
"0.01m以上 〜 0.3m未満", "0.3m以上 〜 1m未満", "1m以上 〜 2m未満",
"2m以上 〜 3m未満", "3m以上 〜 5m未満", "5m以上 〜 10m未満", "10m以上 〜 20m未満")
tsunami <- read_sf("data/A40-16_30.geojson") |>
st_make_valid() |>
mutate(A40_003 = factor(A40_003, levels = hazard)) |>
st_filter(susami)
hazard_pal <- c(
rgb(112, 179, 70, maxColorValue = 255),
rgb(248, 219, 75, maxColorValue = 255),
rgb(225, 136, 58, maxColorValue = 255),
rgb(220, 117, 150, maxColorValue = 255),
rgb(174, 105, 162, maxColorValue = 255),
rgb(213, 68, 56, maxColorValue = 255),
rgb(116, 37, 105, maxColorValue = 255)
)
tm_shape(population) + tm_polygons(fill = NULL) +
tm_shape(tsunami) + tm_polygons(
fill = "A40_003",
fill.scale = tm_scale_categorical(values = hazard_pal),
) +
tm_shape(shelter_polygon) + tm_polygons(col = "red", fill = NULL, lwd = 2) +
tm_layout(text.fontfamily = "BIZ UDPGothic") +
tm_credits(credit) +
tm_basemap(gsi_tile)
沿岸部を中心に津波の浸水が想定されていますが、人口メッシュが存在し、かつ津波浸水が予想されているエリアは、概ね到達圏の範囲内に含まれていることが確認できます。 これは、現在の避難所配置が一定の有効性を持つことを示唆しています。
この記事の執筆に使用したパッケージとそのバージョンは以下の通りです。
| package | loadedversion | source |
|---|---|---|
| sf | 1.1-0 | CRAN (R 4.5.2) |
| sfnetworks | 0.6.5 | CRAN (R 4.5.0) |
| tidygraph | 1.3.1 | CRAN (R 4.5.0) |
| tidyverse | 2.0.0 | CRAN (R 4.5.0) |
| tmap | 4.2 | CRAN (R 4.5.0) |
| tmaptools | 3.3 | CRAN (R 4.5.0) |
| units | 1.0-1 | CRAN (R 4.5.2) |