-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
13-transport-ja.Rmd
826 lines (659 loc) · 79.5 KB
/
13-transport-ja.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
# (PART) 応用 {.unnumbered}
# 交通解析 {#transport}
```{r, include=FALSE}
source("code/before_script.R")
```
```{r transport-setup, include=FALSE}
knitr::opts_chunk$set(warning = FALSE)
```
## 必須パッケージ {.unnumbered}
- この章では、以下のパッケージを使用する[^13-transport-1]
[^13-transport-1]: **nabor** パッケージもインストールされている必要があるが、ロードする必要はない。
```{r 13-transport-1, message=FALSE, results='hide'}
library(sf)
library(dplyr)
library(spDataLarge)
library(stplanr) # 地理交通データを処理
library(tmap) # 地図作成 (Chapter 9 参照)
library(ggplot2) # データ可視化パッケージ
library(sfnetworks) # 空間ネットワークのクラスと関数
```
## イントロダクション {#introduction-13}
交通ほど地理的空間が明確な分野も少ないだろう。
1970年に Waldo Tobler が述べたように、移動の努力 (距離の克服) は、地理学の「第一法則」の中心である [@tobler_computer_1970]。
> Everything is related to everything else, but near things are more related than distant things.
この「法則」は、空間自己相関\index{じこそうかん@自己相関!くうかんてき@空間的}など、地理学の重要な概念の基礎となるものである。
それは、友情のネットワークや生態系の多様性といった多様な現象に適用され、「距離の摩擦」を構成する時間、エネルギー、金銭といった交通コストによって説明することができる。
この観点からすると、交通テクノロジーは破壊的であり、移動する人間やモノを含む地理的な実体間の関係を変化させる。「交通の目的は空間を克服することである」 [@rodrigue_geography_2013]。
交通とは、本質的に空間的な活動であり、出発点「A」から目的点「B」に移動し、その間にある無限の地域を通過することである。
したがって、交通研究者は、移動パターンを理解し、介入によってそのパフォーマンスをどのように改善できるかを理解するため、昔から地理的・計算的手法に注目してきた [@lovelace_open_2021]。
本章では、交通システムの地理的分析について、さまざまな地理的レベルで紹介する。
- **エリア単位**\index{えりあたんい@エリア単位}: 交通パターンは、主な移動手段 (車、自転車、徒歩など) や、特定のゾーンに住む人々の平均移動距離など、ゾーンごとの集計を参照して理解することができる (Section \@ref(transport-zones) で解説する)。
- **希望線** (desire line)\index{きぼうせん@希望線}: 地理空間における場所 (点またはゾーン) 間を何人が移動したか (または移動できたか) を記録した「起点-終点」データを表す直線で、Section \@ref(desire-lines) の話題である。
- **ノード**\index{のーど@ノード} : ノードとは、共通の起点と終点を表すことができる交通システムの点であり、バス停や鉄道駅などの公共交通機関の駅、Section \@ref(nodes) のトピックである。
- **ルート**\index{るーと@ルート}: 希望線に沿ったルート網とノード間のルートを表す線である。
ルート (1 つの線または複数の<u>セグメント</u>の場合がある) と、ルートを生成する<u>ルートエンジン</u>は、Section \@ref(routes) で詳しく述べる。
- **ルートネットワーク** (network)\index{ねっとわーく@ネットワーク}: これらは、ある地域の道路、小道、その他の線形特徴のシステムを表し、Section \@ref(route-networks) で取り上げている。
これらは地理的な特徴 (短いセグメントでネットワーク全体を作り上げる) として表現することもできるし、相互接続されたグラフとして構造化することもできる。異なるセグメント上の交通のレベルは、交通モデルでは「フロー」と呼ばれる [@hollander_transport_2016]。
もうひとつの重要なレベルは、私やあなたのような移動する存在を表す**エージェント**である。
エージェントは、 [MATSim](http://www.matsim.org/) のようなソフトウェアのおかげで、計算によって表現することができる。これは、エージェントベースモデリング (agent-based modelling, ABM)\index{えーじぇんとべーすもでりんぐ@エージェントベースモデリング}のアプローチを用いて、高い空間および時間分解能で交通システムのダイナミクスを捉えるものである [@horni_multi-agent_2016]。
ABM は、R の空間クラスと統合できる可能性が高い交通研究の強力なアプローチであるが [@thiele_r_2014; @lovelace_spatial_2016]、本章の範囲外である。
地理的レベルやエージェントの次に来るのは、ほとんどの交通モデルの分析の基本単位である**トリップ**であり、出発地「A」から目的地「B」までの単一目的の旅である [@hollander_transport_2016]。
トリップは、異なるレベルの交通システムを結合し、単純化すると、<u>ゾーン</u>の重心\index{じゅうしん@重心} (<u>ノード</u>) を結ぶ地理的な<u>希望線</u>として、あるいは交通<u>ルートネットワーク</u>に沿った経路として表現することができる。
この文脈では、<u>エージェント</u>\index{えーじぇんとべーすもでりんぐ@エージェントベースモデリング}は通常、交通ネットワーク内を移動する点である。
交通システムは動的である [@xie_evolving_2011]。
この章では、交通システムの地理的な分析に焦点を当てるが、変化のシナリオをシミュレートするために、この手法をどのように利用できるかについて、Section \@ref(prioritizing-new-infrastructure) にて詳しくみていこう。
地理学上の交通モデルの目的は、このような時空間システムの複雑さを、その本質を捉える形で単純化することにあると解釈できる。
適切なレベルの地理的分析を選択することで、最も重要な特徴や変数を失うことなく、この複雑さを単純化し、より良い意思決定とより効果的な介入を可能にすることができる [@hollander_transport_2016]。
一般的に、モデルは特定の問題を解決するために設計される。
そのため、本章では、次章で紹介する政策シナリオを軸に、Bristol 市内で自転車を増やす方法は何があるかを問う。
Chapter \@ref(location) では、ジオコンピュテーションの応用として、新しい自転車店の立地の優先順位付けを行う。
新しい自転車利用・インフラが効果的に配置されると、人々が自転車利用するようになり、自転車利用・ショップの需要や地域の経済活動を高めることができる。
これは、交通システムの重要な特徴を強調している。交通システムは、より広範な現象や土地利用パターンと密接に関連している。
## Bristol のケーススタディ {#bris-case}
本章で使用する事例は、England 西部の都市 Bristol で、Wales の首都 Cardiff から東に 30 km ほど離れた場所にある。
この地域の交通網の概要は、Figure \@ref(fig:bristol) に示されており、自転車、公共交通、自家用車のための多様な交通インフラが示されている。
```{r 13-transport-2, echo=FALSE, eval=FALSE}
# code that generated the input data - see also ?bristol_ways
# source("https://github.com/geocompx/geocompr/raw/main/code/13-transport-data-gen.R")
# view input data
# summary(bristol_ways)
# summary(bristol_ttwa)
# summary(bristol_region)
library(tmap)
region_all = rbind(bristol_region, bristol_ttwa)
tmap_mode("view")
tm_shape(region_all[1, ], bbox = region_all) +
tm_fill("yellow", col_alpha = 0.5) +
tm_shape(bristol_ways) +
tm_lines(col = "highway", lwd = 2.1, col.scale = tm_scale(values = "-Set1")) +
tm_scalebar() +
tm_shape(region_all) +
tm_borders(col = "black") +
tm_basemap(server = leaflet::providers$Esri.WorldTopoMap)
```
```{r bristol, echo=FALSE, fig.cap="Bristol の交通網は、アクティブ (緑)、公共 (鉄道、青)、自家用車 (赤) の各移動手段を色分けして表現している。黒い境界線は、市街地の境界線 (黄色でハイライト) と、より広い TTWA (Travel To Work Area) を表している。", fig.scap="Bristol's transport network."}
knitr::include_graphics("images/13_bristol.png")
```
Bristol は England で 10 番目に大きい市で、人口は 50 万人であるが、そのトラベルキャッチメントエリア\index{きゃっちめんとえりあ@キャッチメントエリア}はもっと大きい (Section \@ref(transport-zones) 参照)。
市内には航空宇宙、メディア、金融サービス、観光などの企業が集まり、2 つの主要な大学とともに、活気ある経済が展開されている。
Bristol は一人当たりの平均所得が高いが、深刻な貧困地域も含まれている [@bristol_city_council_deprivation_2015]。
交通の面では、Bristol は鉄道や道路の便がよく、アクティブトラベル (訳註: 「アクティブトラベル」とは自転車または徒歩による交通のこと) のレベルも比較的高い。
[Active People Survey](https://www.gov.uk/government/statistical-data-sets/how-often-and-time-spent-walking-and-cycling-at-local-authority-level-cw010#table-cw0103) によると、国民の 19% が月に 1 回以上自転車を利用し、88% が歩いている (全国平均はそれぞれ 15%、81%)。
2011年の国勢調査では、自転車で通勤していると答えた人は全体の 8% だったのに対し、全国ではわずか 3% にとどまっている。
```{r 13-transport-3, eval=FALSE, echo=FALSE}
if (!require(readODS)) {
install.packages("readODS")
}
u = "https://www.gov.uk/government/uploads/system/uploads/attachment_data/file/536823/local-area-walking-and-cycling-in-england-2015.zip"
download.file(u, "local-area-walking-and-cycling-in-england-2015.zip")
unzip("local-area-walking-and-cycling-in-england-2015.zip")
View(readODS::read_ods("Table index.ods"))
cw0103 = readODS::read_ods("cw0103.ods")
View(cw0103)
```
多くの都市と同様に Bristol も渋滞、大気質、運動不足などの大きな問題を抱えている。
自転車は、これらの問題すべてに効率的に取り組むことができる。典型的な[速度](https://en.wikipedia.org/wiki/Bicycle_performance)は、徒歩の時速 4〜6 km に対して時速 15〜20 km と、徒歩よりも自動車による移動を置き換える可能性が大きい。
このため、Bristol の[交通戦略](https://www.bristol.gov.uk/council-and-mayor/policies-plans-and-strategies/bristol-transport-strategy)では、自転車利用について野心的な計画を立てている。
この章では、交通研究における政策的配慮の重要性を強調するため、人々を車から解放し、より持続可能な手段、特に徒歩と自転車に乗せることを任務とする人々 (交通プランナー、政治家、その他の利害関係者) にエビデンスを提供する目的で書かれている。
より広い目的として、ジオコンピュテーションがどのように証拠に基づく交通計画をサポートできるかを示すことである。
この章では、次のことを学ぶ。
- 都市における交通行動の地理的パターンを説明する
- マルチモード・トリップをサポートする主要な公共交通機関のノードを特定する。
- 移動の「希望線」\index{きぼうせん@希望線}を分析、多くの人が短距離をドライブする場所を見つける
- 自動車を減らし自転車を増やすような自転車ルートの位置を特定する
本章の実用的な面から始めるため、次節で、移動パターンに関するゾーンデータをロードする。
このようなゾーンレベルのデータは少ないが、地域の交通システム全体を基本的に理解するためには不可欠な場合が多い。
## 交通ゾーン {#transport-zones}
交通システムは主に線形のフィーチャやノード\index{のーど@ノード} (例えば、ルートや駅) に基づいているが、連続した空間を具体的な単位に分割するために、面的なデータから始めることがしばしば意味を持つ [@hollander_transport_2016]。
調査地域 (ここでは Bristol) を定義する境界線に加えて、交通研究者にとって特に関心の高い 2 つのゾーンタイプ、すなわち発着地ゾーンがある。
多くの場合、発着地には同じ地理的単位が使用される。
しかし、学校や商店などの「トリップアトラクター」が多い地域では、「 [Workplace Zones](https://www.data.gov.uk/dataset/022e455a-b5cc-4247-bfc5-1aaf9da78379/workplace-zones-a-new-geography-for-workplace-statistics)」のような異なるゾーニングシステムが、トリップ先の密度上昇を表すのに適切だろう [@office_for_national_statistics_workplace_2014]。
調査地域を定義する最も簡単な方法は、OpenStreetMap\index{OpenStreetMap} が返す最初のマッチング境界であることが多い。
これは **osmdata** を使用して `bristol_region = osmdata::getbb("Bristol", format_out = "sf_polygon")` のようなコマンドで取得することができる。
この結果、最大の一致する都市地域の境界を表す `sf` オブジェクトが得られ、バウンディングボックスの長方形ポリゴンまたは詳細なポリゴン境界のいずれかが得られる。[^13-transport-2]
イギリスの Bristol については、**spDataLarge** パッケージにある Bristol の公式な境界を表す詳細なポリゴンが返される。
Figure \@ref(fig:bristol) の内側の青い境界を参照。なお、この方法にはいくつかの問題点がある。
[^13-transport-2]: 最初のマッチングで正しい名称が得られない場合、国または地域を指定する必要がある。例えば、アメリカにある Bristol は `Bristol Tennessee` のように指定する。
- OSM から最初に返された境界は、自治体が使用する正式な境界とは異なる場合がある
- OSM が正式な境界線を返したとしても、人々が移動する場所とはほとんど関係がないため、交通研究にとっては不適切かもしれない。
Travel To Work Area (TTWA)) は、水文学的における流域のようなゾーニングシステムを構築することで、これらの問題に対処している。
TTWA はまず、人口の75%が通勤で利用する連続したゾーンと定義されており [@coombes_efficient_1986]、この章ではこの定義を用いる。
Bristol は、周辺の町からのトラベル者を惹きつける主要な雇用主であるため、その TTWA は市域よりもかなり大きい (Figure \@ref(fig:bristol) 参照)。
この交通方向の境界を表すポリゴンは、本章の冒頭でロードした **spDataLarge** パッケージが提供するオブジェクト `bristol_ttwa` に格納されている。
本章で使用する出発地と目的地は同じである。中間の地理的解像度で公式に定義されたゾーン ([公式](https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/bulletins/annualsmallareapopulationestimates/2014-10-23)名称は Middle layer Super Output Areas MSOA) である。
それぞれ約 8,000 人が暮らしている。
このような行政区域は、特定の介入から最も恩恵を受ける可能性のある人々のタイプなど、交通分析に不可欠な状況を提供することができる (例 @moreno-monroy_public_2017)。
ゾーンの地理的解像度は重要である。通常、地理的解像度の高い小さなゾーンが望ましいが、大きな地域で数が多いと、処理に影響を及ぼすことがある。
特に、起点-終点 (OD) 分析は、 ゾーン数に応じて非線形に可能性の数が増加する [@hollander_transport_2016]。
```{block 12-transport-4, type='rmdnote'}
ゾーンが小規模の場合、匿名性のルールに関連する問題も発生する。
ゾーン内の個人の特定を推測できないようにするため、詳細な社会人口統計変数は、低い地理的解像度でしか利用できない。
例えばイギリスでは、年齢や性別による移動手段の内訳は、自治体レベルでは利用できるが 100 世帯程度で構成される出力エリアレベルでは利用できない。
詳細は、www.ons.gov.uk/methodology/geography を参照。
```
本章で使用する 102 のゾーンは、Figure \@ref(fig:zones) に図示されているように `bristol_zones` に格納されている。
人口が密集しているところでは、ゾーンが小さくなっていることに注意しておこう。
`bristol_zones` は、交通に関する属性データは含まず、各ゾーンの名称とコードのみである。
```{r 13-transport-5}
names(bristol_zones)
```
トラベルデータを追加するために、Section \@ref(vector-attribute-joining) で説明されている一般的なタスクである<u>属性結合</u>\index{ぞくせい@属性!けつごう@結合}を実行する。
ここでは、[ons.gov.uk](https://www.ons.gov.uk/help/localstatistics) データポータルで提供されている、英国の2011年国勢調査の出勤時間に関するトラベルデータ `bristol_od` を使用する。
`bristol_od` は、英国の2011年国勢調査によるゾーン間の通勤に関する起点 (Origin)ー終点 (Desitination) (OD) データセットである (Section \@ref(desire-lines) 参照)。
Section \@ref(desire-lines) 1 列目は出発地のゾーン ID、2 列目は目的地のゾーンである。
`bristol_od` は、`bristol_zones` よりも多くの行を持ち、ゾーンそのものよりもゾーン<u>間</u>の移動を表している。
```{r 13-transport-6}
nrow(bristol_od)
nrow(bristol_zones)
```
先ほどのコードチャンクの結果、各ゾーンに 10 組以上の OD ペアがあることがわかった。つまり、下図のように、`bristol_zones` に結合する前に発着地データを集約する必要がある (発着地データは Section \@ref(desire-lines) に記述されている)。
```{r 13-transport-7}
zones_attr = bristol_od %>%
group_by(o) %>%
summarize_if(is.numeric, sum) %>%
dplyr::rename(geo_code = o)
```
上記のチャンクは、
- 原産地別にデータをグループ化した (`o` の列に含まれる)
- `bristol_od` データセットの変数が数値であれば、それを集計して、各ゾーンに住む人の交通手段別の総数を求める[^13-transport-3]
- グループ化変数 `o` の名前を変更し、`bristol_zones` オブジェクトの ID 列 `geo_code` と一致するようにした
[^13-transport-3]: `_if` の接頭辞は、変数に対して `TRUE`/`FALSE` の質問をすることを要求しており、この場合は「それは数値か?」で、真を返す変数のみが要約される。
結果として得られるオブジェクト `zones_attr` は、ゾーンを表す行と ID 変数を持つデータフレームである。
ID が `zones` データセットのものと一致するかどうかは、`%in%` 演算子を用いて以下のように確認することができる。
```{r 13-transport-8}
summary(zones_attr$geo_code %in% bristol_zones$geo_code)
```
その結果、新しいオブジェクトには 102 のゾーンがすべて存在し、`zone_attr`、ゾーン上に結合できる形になっていることがわかった。[^13-transport-4]
これは、結合関数 `left_join()` を使って行われる (なお、`inner_join()` でも同じ結果になる)。
[^13-transport-4]: また、実データで ID が逆方向で一致するかどうかのチェックも重要だろう。
これは、`summary()` コマンドの ID の順序を変更することで可能となる。`summary(bristol_zones $geo_code %in% zones_attr$ geo_code)` --- または、`setdiff()` を次のように使用することで可能である。`setdiff(bristol_zones $geo_code, zones_attr$ geo_code)`
```{r 13-transport-9}
zones_joined = left_join(bristol_zones, zones_attr, by = "geo_code")
sum(zones_joined$all)
names(zones_joined)
```
結果は、調査地域の各ゾーンを起点とするトリップの総数 (ほぼ 25 万) とその移動手段 (自転車、徒歩、自動車、電車) を表す列が新たに追加されている `zones_joined` である。
トリップの起点の地理的な分布は、左パネル (Figure \@ref(fig:zones)) に示されている。
このことから、ほとんどのゾーンは、調査エリア内で 0〜4,000 のトリップを発生させていることがわかる。
Bristol の中心部付近に住む人の移動が増え、郊外に住む人の移動が減っている。
これはなぜだろうか。調査地域内のトリップだけを扱っていることを思い出そう。
周辺ゾーンのトリップ数が少ないのは、周辺ゾーンにいる人の多くが、調査地域外の他の地域へ移動するためであると考えられる。
調査地域外のトリップは、モデルで表現されていないゾーンに行くトリップをカバーする特別な目的地IDによって、地域モデルに含めることができる [@hollander_transport_2016]。
しかし、`bristol_od` のデータは、このようなトリップを無視している。「ゾーン内」モデルということである。
OD データセットが出発地のゾーンに集約されるのと同じように、目的地のゾーンに関する情報を提供するために集約することもできる。
人は、中心部に引き寄せられるように集まる傾向がある。
このことは、右図 (Figure \@ref(fig:zones)) で表される空間分布が比較的不均一であり、最も多い目的地ゾーンが Bristol 市の中心部に集中していることを説明している。
その結果、任意のモードによるトラベル先数を報告する新しい列を含む、`zones_od` が以下のように作成される。
```{r 13-transport-10}
zones_destinations = bristol_od |>
group_by(d) |>
summarize(across(where(is.numeric), sum)) |>
select(geo_code = d, all_dest = all)
zones_od = inner_join(zones_joined, zones_destinations, by = "geo_code")
```
Figure \@ref(fig:zones) の簡易版は、以下のコードで作成する (図を再現するには、本書の GitHub リポジトリの [`code`](https://github.com/geocompx/geocompr/tree/main/code) フォルダ の `13-zones.R` を参照。**tmap**\index{tmap (package)} によるファセット地図の詳細は Section \@ref(faceted-maps) を参照)。
```{r 13-transport-11, eval=FALSE}
qtm(zones_od, c("all", "all_dest")) +
tm_layout(panel.labels = c("Origin", "Destination"))
```
```{r zones, echo=FALSE, fig.cap="地域内に居住・勤務するトリップ (通勤者) 数。左の地図は通勤トリップの出発地、右の地図は目的地のゾーン (`13-zones.R` スクリプトで生成)。", message=FALSE, fig.scap="Number of trips (commuters) living and working in the region."}
# file.edit("code/13-zones.R")
source("code/13-zones.R", print.eval = TRUE)
```
## 希望線 {#desire-lines}
希望線 (desire line) は、出発地と目的地をつなぎ、人々がゾーン間で行きたいと<u>望む</u>場所を表している。
これは、建物や風の強い道路などの障害物がなければ、A-B 間を最も早く移動できる「蜂の飛行線」または「カラスの飛行線」ルートを表している (希望線をルートに変換する方法については、次のセクションで説明する)。
一般的に、希望線は各ゾーンの地理的 (または人口加重) 重心を始点および終点として地理的に表現される。
このセクションでは、このタイプの希望線を作成して使用するが、OD データを基にした分析の空間的なカバレッジと精度を高めるために、複数の開始点と終了点を可能にする「ジッタリング」技術は知っておく価値がある [@lovelace_jittering_2022b]。
データセット `bristol_od` に、希望線を表すデータをすでに読み込んでいる。
この起点ー終点 (OD) データフレームオブジェクトは、`o` で表されるゾーンと `d`、Table \@ref(tab:od) で示されるゾーン間の移動人数を表している。
OD データをすべてのトリップで並べ、上位5つだけをフィルタリングするには、次のように入力する (非空間属性操作の詳細については、Chapter \@ref(attr) を参照)。
```{r 13-transport-12}
od_top5 = bristol_od |>
slice_max(all, n = 5)
```
```{r od, echo=FALSE}
od_top5 |>
knitr::kable(
caption = paste("Bristol ODデータフレームの上位5組の起点と終点の",
"サンプルで、調査地域のゾーン間の",
"トラベル希望線を表している。"),
caption.short = "Sample of the origin-destination data.",
booktabs = TRUE)
```
この表は、Bristol での通勤・通学パターンを示すものである。
これは、上位 5 つの OD ペアにおいて、徒歩が最も人気のある交通手段であること、ゾーン `E02003043` が人気のある目的地であること (Bristol の中心部、上位 5 つの OD ペアの目的地)、ゾーン `E02003043` のある部分から別の部分への<u>ゾーン内</u>トリップ (Table \@ref(tab:od) の最初の行) がデータセットで最も移動した OD ペアであることを実証している。
しかし、政策的な観点から見ると、Table \@ref(tab:od) で示される生データは、限られた用途にしか使えない。2,910 組の OD のうち、ごく一部しか含まれていないという事実を除けば、政策的措置が必要な場所は<u>どこ</u>か、徒歩や自転車による移動が<u>どの程度の割合を占める</u>のかについては、ほとんどわからないのである。
次のコマンドは、これらのアクティブモードによって作られる各希望線の割合を計算する。
```{r 13-transport-13}
bristol_od$Active = (bristol_od$bicycle + bristol_od$foot) /
bristol_od$all * 100
```
OD ペアは、大きく分けて<u>ゾーン間</u>と<u>ゾーン内</u>の 2 種類がある。
ゾーン間 OD ペアは、目的地と出発地が異なるゾーン間の移動を表する。
ゾーン内 OD ペアは、同一ゾーン内の移動を表す (Table \@ref(tab:od) の上段参照)。
以下のコードチャンクでは、`od_bristol` をこの2種類に分割している。
```{r 13-transport-14}
od_intra = filter(bristol_od, o == d)
od_inter = filter(bristol_od, o != d)
```
次のステップは、ゾーン間 OD ペアを、**stplanr**\index{stplanr (package)} 関数 `od2line()` を用いて地図上にプロットできる希望線を表す `sf` オブジェクトに変換することである。[^13-transport-5]
[^13-transport-5]:`od2line()` は、 オブジェクトの最初の 2 列の ID を、地理的な オブジェクトの ID 列にマッチングさせることで動作する。
`bristol_od` `zones_od` `zone_code` なお、この操作は警告を発するが、これは `od2line()` が各起点と終点のペアをその起点と終点のゾーンの<u>重心</u>\index{じゅうしん@重心}に割り当てることで動作するためである。
実際の使用では、投影データから生成された重心を使用するか、できれば<u>人口重み付け</u>された重心を使用することになるだろう [@lovelace_propensity_2017]。
```{r 13-transport-15, warning=FALSE}
desire_lines = od2line(od_inter, zones_od)
```
結果の図は Figure \@ref(fig:desire) に示されており、その簡易版は以下のコマンドで作成される (図を正確に再現するには `13-desire.R` のコードを、 **tmap**\index{tmap (package)} による視覚化の詳細については Chapter \@ref(adv-map) を参照)。
```{r 13-transport-16, eval=FALSE}
qtm(desire_lines, lines.lwd = "all")
```
```{r desire, echo=FALSE, warning=FALSE, message=FALSE, fig.cap="Bristol のトリップパターンを表す希望線は、幅がトリップ数、色がアクティブモード (徒歩と自転車) によるトリップの割合を表している。4 本の黒い線は、Table 13.1のゾーン間 OD ペアを表している。", fig.asp=0.8, fig.scap="Desire lines representing trip patterns in Bristol."}
source("code/13-desire.R", print.eval = TRUE)
```
この地図から、地域の交通パターンを支配しているのは中心市街地であり、そこに政策を優先させるべきであることがわかるが、周辺には副都心も多く見られる。
希望線は交通システムの重要な一般化された構成要素である。
より具体的な構成要素としては、(希望線のような仮想的な直線ではなく) 特定の目的地を持つノードがある。
ノードについては次節で述べる。
## ノード {#nodes}
地理的な交通データにおけるノード\index{のーど@ノード}は、ネットワーク\index{ねっとわーく@ネットワーク}を構成する主に一次元のフィーチャ (線) とゼロ次元のフィーチャ (点) である。
交通ノードには 2 種類ある。
1. ネットワーク\index{ねっとわーく@ネットワーク}上に直接存在しないノード\index{のーど@ノード}、例えばゾーン重心\index{じゅうしん@重心} (次のセクションで取り上げる) あるいは家や職場などの個人の発着地
2. 交通網の一部であるノード。
技術的には、ノードは交通ネットワーク上のどの点にも位置することができるが、実際には、ルートの交差点 (ジャンクション) やバス停や駅など交通ネットワークに出入りする点など、特殊な頂点である場合が多い[^13-transport-6]
[^13-transport-6]: **sfnetworks** パッケージの関数 [`st_network_blend()`](https://luukvdmeer.github.io/sfnetworks/reference/st_network_blend.html) により、ネットワーク上またはネットワーク外の任意の点への近接性に基づいて、ネットワーク上に新しいノードを作成することができる。
交通ネットワークは、グラフ\index{ぐらふ@グラフ}として表すことができ、その中で各セグメントは、ネットワーク内の 1 つ以上の他のエッジ\index{えっじ@エッジ}に (地理的な線を表すエッジを介して) 接続されている。
ネットワーク外のノードは「重心コネクタ」で追加可能。重心コネクタとは、ネットワーク上の近くのノードへの新しいルートセグメントである [@hollander_transport_2016] 。[^13-transport-7]
ネットワークの各ノード\index{のーど@ノード}は、ネットワーク上の個々のセグメントを表す 1 つ以上の「エッジ」によって接続されている。
交通ネットワークがグラフとして表現できることを Section \@ref(route-networks) で確認する。
[^13-transport-7]: これらのコネクタは、その近辺の交通量を過大に見積もる可能性があるため、その位置は慎重に選ぶ必要がある [@jafari_investigation_2015]。
公共交通機関の駅や停留所は特に重要なノード\index{のーど@ノード}である。道路の一部であるバス停、または線路から数百メートルの歩行者入口ポイントによって表される大規模な鉄道駅のいずれかのタイプのノードとして表現されることができる。
ここでは、Bristol における自転車の増加という研究課題に関連して、公共交通機関のノード\index{のーど@ノード}を説明するために鉄道駅を使用しよう。
鉄道駅のデータは、`bristol_stations` の **spDataLarge** で提供されている。
通勤において自動車から他の交通への転換を阻む共通の障壁は、自宅から職場までの距離が遠すぎると徒歩や自転車では無理だということである。
公共交通機関は、都市への一般的なルートにおいて、高速かつ大量に利用できるオプションを提供することで、この障壁を軽減することができる。
アクティブトラベルの観点から、公共交通機関を利用した長距離移動の「行程」は、旅を 3 つに分けている。
- 住宅地から公共交通機関の駅までの起点となる行程
- 公共交通機関 (通常、出発地の最寄り駅から目的地の最寄り駅まで)
- 降車駅から目的地までの行程
Section \@ref(desire-lines) で行った分析に基づき、公共交通機関のノードを使って、バスと (この例では) 鉄道を利用できるトラベルのための 3 分割の希望線を構築することができる。
最初の段階は、公共交通機関の利用が多い希望線を特定することである。ここでは、先に作成したデータセット `desire_lines` にすでに電車での移動回数を表す変数が含まれているので簡単である (公共交通機関の利用可能性は、[OpenTripPlanner](http://www.opentripplanner.org/) などの公共交通ルート探索\index{るーとけんさく@ルート検索}サービスを使って推定することも可能)。
アプローチを簡単にするために、レールの使用量の上位 3 つの希望線\index{きぼうせん@希望線}のみを選択することにする。
```{r 13-transport-20}
desire_rail = top_n(desire_lines, n = 3, wt = train)
```
そこで、これらの線を 3 つに分解し、公共交通機関の乗り換えを表現することにする。
これは、希望線を、トラベルの出発地、公共交通機関、目的地の 3 つの線ジオメトリからなる複合線に変換することで実現できる。
この作業は、行列の作成 (起点、終点、鉄道駅を表す「経由点」)、最近傍\index{さいきんぼう@最近傍}の特定、複合線\index{ふくごうせん@複合線}への変換の 3 段階に分けることができる。
この一連の処理は、`line_via()` 関数が行う。
この **stplanr**\index{stplanr (package)} 関数は入力された線と点を受け取り、希望線のコピーを返す (この動作の詳細については geocompr.github.io ウェブサイトの [Desire Lines Extended](https://geocompr.github.io/geocompkg/articles/linevia.html) vignette と `?line_via` を参照)。
出力は入力と同じだが、公共交通機関のノードを使った旅を表す新しいジオメトリの列がある (以下に示す)。
```{r 13-transport-21}
ncol(desire_rail)
desire_rail = line_via(desire_rail, bristol_stations)
ncol(desire_rail)
```
Figure \@ref(fig:stations) に示すように、最初の `desire_rail` の行に、自宅から出発駅まで、そこから目的地まで、そして最後に目的地から目的地までの移動を表す 3 つのジオメトリリスト列\index{りすとれつ@リスト列}が追加されている。
この場合、目的地までの距離は非常に短いが (歩行距離)、出発地までの距離は十分であるため、往路の駅まで自転車での移動を促すためのインフラ投資を正当化することができる。Figure \@ref(fig:stations) にある 3 つの出発地の駅周辺の住宅地では、人々が通勤するために自転車を利用することができる。
```{r stations, echo=FALSE, message=FALSE, warning=FALSE, fig.cap="鉄道利用率の高い直線的な希望線 (黒) を、公共交通機関 (グレー) を経由して出発駅 (赤) へ、そして目的地 (ごく短い青線) へという 3 レグに変換する中間点として使用される駅ノード (赤い点)。", fig.scap="Station nodes."}
# zone_cents = st_centroid(zones_od)
zone_cents = st_centroid(zones_od)
zone_cents_rail = zone_cents[desire_rail, ]
bb = tmaptools::bb(desire_rail, ext = 1.1)
desire_rail_plot = rbind(
st_sf(data.frame(Geometry = "Desire line (original)"), geometry = desire_rail$geometry),
st_sf(data.frame(Geometry = "Leg 1 (origin to station)"), geometry = desire_rail$leg_orig),
st_sf(data.frame(Geometry = "Leg 2 (station to station)"), geometry = desire_rail$leg_via),
st_sf(data.frame(Geometry = "Leg 3 (station to destination)"), geometry = desire_rail$leg_dest)
)
desire_rail_plot = desire_rail_plot |>
mutate(lty = case_when(Geometry == "Desire line (original)" ~ 2, TRUE ~ 1)) |>
mutate(size = case_when(Geometry == "Desire line (original)" ~ 1, TRUE ~ 2))
bristol_rail_points = rbind(
st_sf(data.frame(
Node = "Origin and destination locations",
col = "black"
), geometry = zone_cents_rail$geometry),
st_sf(data.frame(
Node = "Public transport node",
col = "red"
), geometry = bristol_stations$geometry)
)
tm_shape(zones_od) +
tm_fill(fill_alpha = 0.2, lwd = 0.1) +
tm_shape(desire_rail_plot, bbox = bb, is.main = TRUE) +
tm_lines(col = "Geometry",
col.scale = tm_scale(values = "Set2"),
col.legend = tm_legend(position = tm_pos_in("left", "top")),
lwd = 2,
lty = "lty",
lty.scale = tm_scale_categorical(),
lty.legend = tm_legend_hide()) +
tm_shape(bristol_rail_points) +
tm_symbols(fill = "col", size = 0.75) +
tm_scalebar()
```
## ルート {#routes}
\index{るーと@ルート}
地理学者から見れば、ルートとは直線でなくなった希望線\index{きぼうせん@希望線}である。出発地と目的地は同じだが、A から B へのルートはより複雑である。
ルートは、ローカルまたはリモートで実行されるルート探索サービスを使用して、希望線 (より一般的には起点と終点のペア) から生成される。
希望線が 2 つの頂点 (始点と終点) しか持たないのに対し、ルートは任意の数の頂点を持つことができ、A-B 間の点を直線で結んだものと定義される。これは線ジオメトリ (linestring) の定義である。
長距離をカバーするルートや複雑なネットワークに沿ったルートは何千もの頂点を持つことができるが、グリッドベースや簡略化された道路ネットワーク上のルートは頂点数が少なくなる傾向がある。
ルートは、希望線から生成されるか、より一般的には、希望線を表す座標ペアを含むマトリックスから生成される。
このルート検索プロセスは、広義に定義されたさまざまな<u>ルート検索エンジン</u>、すなわち、起点から目的地までの移動方法を記述した形状と属性を返すソフトウェアやウェブサービスによって行われる。
ルート検索エンジンは、以下のように、R と相対的に実行される<u>場所</u>に基づいて分類することができる。
- ルート計算を可能にする R パッケージを使用したメモリ内ルート検索 (Section \@ref(memengine))
- R から呼び出せる、R の外部にあるローカルホスティングのルート検索エンジン (Section \@ref(localengine))
- R から呼び出せる Web API を提供する、外部エンティティによるリモートホスティング型ルート検索エンジン (Section \@ref(remoteengine))
それぞれについて説明する前に、ルート検索エンジンを分類する他の方法について概説しておく価値がある。
ルート検索エンジンはマルチモードである。つまり、複数の交通手段からなるトリップを計算することができるし、そうでないこともある。
マルチモードなルート検索エンジンは、それぞれが異なる交通手段で作られた複数の<u>旅程 (leg)</u>からなる結果を返すことができる。
住宅地から商業地までの最適なルートは、(1) 最寄りのバス停まで歩く、(2) 目的地に最も近いノードまでバスに乗る、(3) 目的地まで歩く、などが考えられる (入力パラメータ式がある場合)。
この 3 つの旅程間の移行点は、一般的に「入口」(ingress) と「出口」(egress) と呼ばれ、公共交通機関の乗り降りを意味する。
R5 のようなマルチモードなルート検索エンジンは、OpenStreetMap Routing Machine (OSRM) のような「ユニモーダル」ルート検索エンジンよりも高度で、入力データ要件も大きくなる (Section \@ref(localengine) に記載)。
マルチモードエンジンの大きな強みは、電車やバスなどの「トランジット」(公共交通機関) トリップを表現する能力にある。
マルチモデルルート検索エンジンは、公共交通機関のネットワークを表す入力データセットを必要とする。一般的には、General Transit Feed Specification ([GTFS](https://developers.google.com/transit/gtfs)) ファイルで、これは [**tidytransit**](https://r-transit.github.io/tidytransit/index.html) および [**gtfstools**](https://ipeagit.github.io/gtfstools/) パッケージ内の関数で処理できる (GTFS ファイルを処理する他のパッケージやツールは利用可能)。
特定の (公共ではない) 交通手段に焦点を当てたプロジェクトでは、単一モードなルート検索エンジンで十分かもしれない。
ルート検索エンジン (または設定) を分類するもう一つの方法は、ルート、レッグ、セグメントという出力の地理的なレベルによるものである。
### ルート、レッグ、セグメント {#route-legs-segments}
ルート検索エンジンは、ルート、レッグ、セグメントという 3 つの地理的なレベルで出力を生成することができる。
- **ルート** レベルの出力には、出発地と目的地のペアごとに 1 つのフィーチャ (通常はデータフレーム表現におけるマルチライン文字列と関連する行) が含まれ、トリップごとに 1 つのデータ行があることを意味する
- **レッグ** レベルの出力には、各起点と終点のペアに 1 つのフィーチャと関連する属性が含まれまる。1 つのモードを含むだけのトリップの場合 (たとえば、自宅から職場まで車で行き、車まで の短い徒歩は無視)、レッグはルートと同じで、車の旅になる。公共交通機関を利用するトリップの場合、レッグは重要な情報を提供する。**r5r** の関数 `detailed_itineraries()` はレッグを返すが、紛らわしいことに、これは「セグメント」と呼ばれることもある
- セグメントレベルの出力は、交通ネットワークの各小セクションのレコードを持つ、ルートに関する最も詳細な情報を提供する。一般的にセグメントは、OpenStreetMap の道と同じか、同じ長さになっている。**cyclestreets** 関数 `journey()` はセグメントレベルのデータを返し、これは **stplanr** の `route()` 関数が返す出発地と目的地レベルのデータでグループ化することによって集約できる
ほとんどのルート検索エンジンは、デフォルトでルートレベルを返すが、マルチモードエンジンは一般的にレッグレベル (単一の交通モードによる連続した移動ごとに 1 つの機能) の出力を提供する。
セグメントレベルの出力は、より詳細な情報を提供するという利点がある。
**cyclestreets** パッケージは、ルートごとに複数の「静かさ」レベルを返し、サイクルネットワークの「最も弱いリンク」の特定を可能にする。
セグメントレベル出力の欠点は、ファイルサイズの増大と余分な詳細情報に関連する複雑さである。
ルートレベルの結果は、関数 `stplanr::overline()` を使用してセグメントレベルの結果に変換することができる [@morgan_travel_2020]。
セグメントやレッグレベルのデータを扱う場合、トラベルの開始点と終了点を表す列でグループ化し、セグメントレベルのデータを含む列を要約/集計することで、ルートレベルの統計情報を返すことができる。
### R のメモリ内ルート検索 {#memengine}
R のルート検索エンジンは、R のオブジェクトとして<u>メモリ</u>に格納されているルートネットワークをルート計算のベースとして使用することができる。
選択肢としては、[**sfnetworks**](https://luukvdmeer.github.io/sfnetworks/) \index{sfnetworks (package)}、 [**dodgr**](https://urbananalyst.github.io/dodgr/)、 [**cppRouting**](https://github.com/vlarmet/cppRouting) といったパッケージがあり、それぞれ次節のテーマであるルートネットワークを表す独自のクラス体系を提供している。
R ネイティブなルート検索は高速で柔軟な反面、現実的なルート計算のための専用ルート検索エンジンに比べて、一般に設定が困難である。
ルート検索は難しい問題であり、ダウンロードしてローカルでホストできるオープンソースのルート検索エンジンに何百時間もの時間が費やされている。
一方、R ベースのルート検索エンジンは、モデル実験や、ネットワークへの変更の影響の統計的分析に適しているかもしれない。
ルートネットワークの特性 (または異なるルートセグメントの種類に関連する重み) を変更し、ルートを再計算し、多くのシナリオの下で結果を分析することを1つの言語で行うことは、研究用途にメリットがある。
### ローカル型専用ルート検索エンジン {#localengine}
**ローカル型**ルート検索エンジンには、OpenTripPlanner、[Valhalla](https://github.com/valhalla/valhalla)、OpenStreetMap Routing Machine (OSRM) (これは「ユニモーダル」のみ対応)、R5 などがある。
R からこうしたサービスにアクセスするには、**opentripplanner**、[**valhallr**](https://github.com/chris31415926535/valhallr)、**r5r**、[**osrm**](https://github.com/riatelab/osrm) などのパッケージがある [@morgan_opentripplanner_2019; @pereira_r5r_2021]。
ローカルにホストされたルート検索エンジンは、ユーザのコンピュータ上で実行されるが、R とは別のプロセスで実行される。
利点としては、実行速度が速く、異なる交通手段に対する重み付けプロファイルを制御できるという点がある。
反対に欠点は、複雑なネットワークをローカルに表現することが難しい、定義済みルートプロファイルがない、時間的ダイナミクス (例えば交通)、特殊なソフトウェアが必要となる、などが挙げられる。
### リモート型専用ルート検索エンジン {#remoteengine}
**リモート型**\index{るーとけんさく@ルート検索}ルート検索エンジンは、Web API\index{API} を使用して、起点と終点に関するクエリを送信し、専用のソフトウェアが動作する強力なサーバーで生成された結果を返す。
OSRM の一般公開されているサービスのような、オープンソースルート検索エンジンに基づくルート検索サービスは、R から呼び出された場合、ローカルにホストされたインスタンスと全く同じように動作し、単に更新される「ベース URL」を指定する引数を必要とするだけである。
しかし、外部のルート検索サービスは専用のマシンでホストされているため (通常、正確なルートを生成するインセンティブを持つ営利企業が資金を提供している)、以下のような利点がある。
- 世界中 (または通常少なくとも広い地域) にルート検索サービスを提供すること
- 確立されたルート検索サービスは、通常定期的に更新され、トラフィックレベルに対応することができる
- ルート検索サービスは通常、専用のハードウェアとソフトウェアで実行され、ロードバランサーなどのシステムにより一貫したパフォーマンスを確保できる
リモートルート検索サービスのデメリットとしては、バッチジョブができない場合の速度 (ルートごとにインターネットでのデータ転送に頼ることが多い)、価格 (例えば Google ルート検索 API では、無料のクエリ回数に制限がある)、ライセンス問題などが挙げられる。
[**googleway**](http://symbolixau.github.io/googleway/) と [**mapbox**](https://walker-data.com/mapboxapi/articles/navigation.html) という二つのパッケージは、それぞれ Google と Mapbox のルート検索サービスへのアクセスを提供する\index{API}。
無料 (ただし料金に制限あり) のルート検索サービスは、 [OSRM](http://project-osrm.org/)、 [**osrm**](https://rgeomatic.hypotheses.org/category/osrm) からアクセスできる [openrouteservice.org](https://openrouteservice.org/)、[**openrouteservice**](https://github.com/GIScience/openrouteservice-r) などがある。最後のパッケージは CRAN にはない。
また、[CycleStreets.net](https://www.cyclestreets.net/) のような、より具体的なルート検索サービスもある。これは、「サイクリストによるサイクリストのための」サイクル・ジャーニー・プランナーで非営利の交通技術会社である。
R では [**cyclestreets**](https://rpackage.cyclestreets.net/) パッケージを通して CycleStreets ルートにアクセスできるが、多くのルート検索サービスには R インターフェースがなく、パッケージ開発の大きなチャンスとなっている。Web API へのインターフェースを提供する R パッケージを構築することはやりがいのある経験になることだろう。
### 縮約階層とトラフィック割り当て {#contraction-hierarchies-and-traffic-assigment}
縮約階層とトラフィック割当は、交通モデリングにおける高度だが重要なトピックである。
多くの経路を計算することは計算資源を大量に消費し、何時間もかかることがあるため、経路計算を高速化するためのアルゴリズムがいくつか開発された。
**縮約階層** (contraction hierarchy) はよく知られたアルゴリズムで、ネットワークのサイズにもよるが、ルート検索課題の大幅な (場合によっては 1,000 倍以上の) 高速化につながる。
縮約階層は、前のセクションで述べたルート検索エンジンの舞台裏で使われている。
交通の割当てはルート検索と密接に関係する問題で、実際には 2 点間の最短経路が最速とは限らず、特に混雑している場合は最速になる。
この処理では、\@ref(desire-lines) で説明するような OD データセットを受け取り、 ネットワークの各セグメントにトラフィックを割り当てて、\@ref(route-networks) で説明するような ルートネットワークを生成する。
この問題に対する解は、Wardrop の利用者均衡の原則である。この原則は、現実に即して、ネットワーク上のフローを見積もる際に混雑を、数学的に定義されたコスト・フロー関係を参照しながら考慮すべきであることを示している [@wardrop_theoretical_1952]。
この最適化問題は、[**cppRouting**](https://github.com/vlarmet/cppRouting) パッケージで実装されている反復アルゴリズムによって解くことができる。このパッケージは、高速ルート検索のための縮約階層も実装している。
### ルート検索: 実例紹介
前のセクションで生成された希望線を<u>すべて</u>ルート探索\index{るーとけんさく@ルート検索}する代わりに、政策上関心のある希望線\index{きぼうせん@希望線}に焦点を当てることにする。
データ全体を処理する前に、一部のデータに対して計算量の多い処理を実行することは、賢明な方法である。ルート検索も然り。
ルート検索は、ジオメトリが詳細でかつローとオブジェクトの属性が多いと、時間とメモリを消費し、オブジェクトが巨大になる。
このため、この節では、ルートを計算する前に希望線をフィルタする。
自転車トラベルの利点は、自動車トラベルを置き換えるときに最も大きく、比較的短いトラベルは長いトラベルよりも自転車に乗る可能性が高いという観察に基づいて、自転車トラベルの可能性を推定することに重点を置いて希望線のサブセットをフィルタリングする [@lovelace_propensity_2017]。
短いトリップ (5 km 程度、時速 20 km で 15 分程度で走れる距離) は、比較的自転車で移動する確率が高く、電動自転車で移動すると最大距離が延びる [@lovelace_propensity_2017]。
これらの考察に基づき、希望線をフィルタし、多くの (100 以上の) 短い (ユークリッド距離 2.5〜5 km) トリップを駆動する OD ペアを表すオブジェクト `desire_lines_short` を返す次のコードチャンクに反映しよう。
```{r 13-transport-17, message=FALSE}
desire_lines$distance_km = as.numeric(st_length(desire_lines)) / 1000
desire_lines_short = desire_lines |>
filter(car_driver >= 100, distance_km <= 5, distance_km >= 2.5)
```
上記のコードで、`st_length()` は Section \@ref(distance-relations) にあるように、各希望線の長さを計算している。
Section \@ref(vector-attribute-subsetting) で述べるように、**dplyr** の `filter()` 関数で、上記の条件に基づいて `desire_lines` データセットにフィルタをかけている\index{ふぃるたそうさ@フィルタ操作|ぞくせい@see{ぞくせい@属性!ぶぶんしゅうごう@部分集合}}。
次に、この希望線をルートに変換する。
これは一般に公開されている OSRM サービスを用いて、以下のコードにある **stplanr** 関数 `route()` と `route_osrm()`\index{stplanr (package)} で行われる。
```{r 13-transport-18, message=FALSE}
routes_short = route(l = desire_lines_short, route_fun = route_osrm,
osrm.profile = "bike")
```
出力は `routes_short` で、(少なくとも OSRM ルート検索エンジンによれば) 自転車利用に適したトランスポートネットワーク\index{ねっとわーく@ネットワーク} 上のルートを表す `sf` オブジェクトで、各希望線に対して一つずつ出力される。
注意: 上記のコマンドのような外部のルート検索エンジンの呼び出しは、インターネット接続 (そして、今回は必要ないが、環境変数に保存された API キーも必要な場合がある) でのみ動作する。
`desire_lines` オブジェクトに含まれる列に加えて、新しいルートデータセットには `distance` (今回はルートの距離を参照) と `duration` (秒単位) の列が含まれ、それぞれのルートについて有用な追加情報を提供する可能性がある。
自転車ルートと並行する車による短い希望線をプロットする。
道路網への介入に優先順位をつける効果的な方法を提供するため、ルート幅を置き換えられる可能性のある車の旅の数に比例させる [@lovelace_propensity_2017]。
Figure \@ref(fig:routes) は、自動車による短距離ルートを示している (ソースコードは github.com/geocompx を参照)。[^13-transport-8]
[^13-transport-8]: なお、赤いルートと黒い希望線は、まったく同じ地点からスタートしているわけではない。
これは、ゾーンの重心がルートネットワーク上に存在することはほとんどなく、重心に最も近い交通ネットワークノードからルートが発信されるためである。
また、ルートはゾーン重心を起点とすると仮定しているが、これは可能な起点と目的地のすべての組み合わせの間の最短ルートを計算するのに必要な計算資源を減らすために交通モデルで使用される単純化した仮定であることに注意 [@hollander_transport_2016]。
```{r routes, warning=FALSE, fig.cap="短距離 (ユークリッド距離 5 km 未満) の自動車移動が多数 (100 回以上) 行われたルート (赤) と、同じ移動を表す希望線 (黒) および重心 (点) を重ねたもの。", fig.scap="Routes along which many car journeys are made.", echo=FALSE}
# TODO (low priority, RL): add a facetted plot showing network cleaning/overline functions
# waldo::compare(
# sf::st_crs(desire_lines_short),
# sf::st_crs(routes_short)
# )
routes_plot_data = rbind(
desire_lines_short |> transmute(Entity = "Desire lines") |> sf::st_set_crs("EPSG:4326"),
routes_short |> transmute(Entity = "Routes") |> sf::st_set_crs("EPSG:4326")
)
zone_cents_routes = zone_cents[desire_lines_short, ]
tm_shape(zones_od) +
tm_fill(fill_alpha = 0.2, lwd = 0.1) +
tm_shape(desire_lines_short, is.main = TRUE) +
tm_lines(lty = 2) +
tm_shape(routes_short) +
tm_lines(col = "red") +
tm_add_legend(title = "Entity", labels = c("Desire lines", "Routes"),
type = "lines", col = c("black", "red"), lty = c(2, 1),
position = tm_pos_in("left", "top")) +
tm_shape(zone_cents_routes) +
tm_symbols(fill = "black", size = 0.5) +
tm_scalebar()
```
インタラクティブ地図で可視化してみると、Bristol 中心部から約 10 km 北の Bradley Stoke 周辺で多くの短距離自動車トラベルが行われていることがわかる。
[Wikipedia](https://en.wikipedia.org/wiki/Bradley_Stoke) によると、Bradley Stoke は「民間投資によって建設されたヨーロッパ最大のニュータウン」であり、公共交通機関の整備が限定的であることを示唆している。
さらに、この町は、「M4 高速道路と M5 高速道路など、大規模な (自転車利用に不利な) 道路構造に囲まれている」 [@tallon_bristol_2007]。
トラベル希望線\index{きぼうせん@希望線}をトラベルルートに変換することは、政策の観点から多くの利点がある。
ルート検索エンジンによって計算された正確なルートをたどるトリップがどれだけあるか (あったとしても) 確認することはできないことを覚えておくことが重要である。
しかし、ルートや道路・区間レベルの結果は、政策に大きく関連する可能性がある。
ルートセグメントの結果は、利用可能なデータ に従って、最も必要な場所に投資を優先させることを可能にすることができる [@lovelace_propensity_2017]。
## ルートネットワーク {#route-networks}
\index{ねっとわーく@ネットワーク}
一般に路線は、希望線と同じレベルのデータ (または重複する可能性のあるセグメントのレベル) を含むが、路線網データセットは、交通網をほぼ完全に表現するものである。
路線網の各セグメント (交差点間の連続した道路区間にほぼ相当) は、一度だけ存在する。しかし、セグメントの平均長はデータソースによって異なる (このセクションで使用した OSM 由来の `bristol_ways` データセットのセグメントの平均長は 200 m 強で、標準偏差は 500 m 近い)。
セグメント長にばらつきがあるのは、地方では交差点が遠く、密集した都市部では数メートルおきに交差点があるなど、セグメントの切れ目があるためと思われる。
路線網は、インプットの場合もあれば、アウトプットの場合もあり、両方の場合もある。
ルート計算を行う交通研究は、内部または外部のルート検索エンジンのルートネットワークデータを必要とする (後者の場合、ルート網データは必ずしも R にインポートされるわけではない)。
しかし、路線ネットワークは、多くの交通研究プロジェクトにおいて重要なアウトプットでもある。特定の区間で発生しうるトリップ数などのデータをまとめ、路線ネットワークとして表現することで、最も必要なところに優先的に投資することができる。
\index{ねっとわーく@ネットワーク}
ルートレベルのデータから得られる出力としてルートネットワークを作成する方法を示すために、モーダルシフトの簡単なシナリオを想像してみたい。
ルート距離 0~3 km の車移動の 50% が自転車に置き換えられ、その割合はルート距離が 1 km 増えるごとに 10 ポイントずつ下がり、6 km の車移動の 20% が自転車に置き換えられ、8 km 以上の車移動が自転車に置き換えられないと想像しよう。
これはもちろん非現実的なシナリオ [@lovelace_propensity_2017] ではあるものの、出発点としては有用であろう。
この場合、自動車から自転車へのモーダルシフトを次のようにモデル化することができる。
```{r uptakefun}
uptake = function(x) {
case_when(
x <= 3 ~ 0.5,
x >= 8 ~ 0,
TRUE ~ (8 - x) / (8 - 3) * 0.5
)
}
routes_short_scenario = routes_short |>
mutate(uptake = uptake(distance / 1000)) |>
mutate(bicycle = bicycle + car_driver * uptake,
car_driver = car_driver * (1 - uptake))
sum(routes_short_scenario$bicycle) - sum(routes_short$bicycle)
```
約 4,000 のトリップが車から自転車に切り替わるというシナリオを作成したので、この更新されたモデル化された自転車利用活動がどこで行われるかをモデル化することができるようになった。
これには、**stplanr** パッケージの関数 `overline()` を使用する。
この関数は、ルートと要約する属性の名前を含むオブジェクトを第 1 と第 2 の引数として受け取り、分岐点 (2 つ以上の線の形状が出会うところ) で線を切断し、それぞれのユニークなルートセグメント [@morgan_travel_2020] について集約した統計量を計算するものである。
```{r rnet1}
route_network_scenario = overline(routes_short_scenario, attrib = "bicycle")
```
前出の 2 つのコードチャンクの出力は、以下の Figure \@ref(fig:rnetvis) に要約している。
```{r rnetvis, out.width="49%", fig.show='hold', fig.cap="距離関数による自動車から自転車への移行率 (左) と、この関数のルートネットワークレベルの結果 (右)。", echo=FALSE, fig.height=9.5, dev="ragg_png"}
routes_short_scenario |>
ggplot() +
geom_line(aes(distance / 1000, uptake), color = "red", linewidth = 3) +
labs(x = "ルート距離 (km)", y = NULL, title = "自動車から自転車へ変換した割合") +
scale_y_continuous(labels = scales::percent) + theme(text = element_text(family = "HiraginoSans-W3"))
tm_shape(zones_od) +
tm_fill(fill_alpha = 0.2, lwd = 0.1) +
tm_shape(route_network_scenario, is.main = TRUE) +
tm_lines(lwd = "bicycle",
lwd.scale = tm_scale(values.scale = 1.5),
lwd.legend = tm_legend(title = "1日あたりの自転車トリップ数\n(modeled, one direction)",
position = tm_pos_in("left", "top")),
col = "red")
```
道路種別や幅員などの属性がセグメントレベルで記録されている交通網は、一般的な路線網の一種である。
このような路線網のデータセットは、OpenStreetMap から世界中で入手でき、**osmdata**\index{osmdata (package)} や **osmextract**\index{osmextract (package)} などのパッケージでダウンロードすることが可能である。
OSM\index{OpenStreetMap}のダウンロードと準備の時間を節約するために、以下の出力に示すように、ケーススタディ地域の交通ネットワークのサンプルを表す LINESTRING ジオメトリと属性を持つ `sf` オブジェクト、**spDataLarge** パッケージから `bristol_ways` オブジェクトを使用する (詳細は `?bristol_ways` を参照)。
```{r 13-transport-22}
summary(bristol_ways)
```
出力は、`bristol_ways` が交通ネットワーク\index{ねっとわーく@ネットワーク}上の 6,000 以上のセグメントを表していることを示している。
このネットワークや他の地理的なネットワークは、数学的なグラフとして表現することができ、ネットワーク上のノード\index{のーど@ノード}とエッジ\index{えっじ@エッジ}で接続されている。
このようなグラフを扱うために、多くの R パッケージが開発されており、特に **igraph**\index{igraph (package)} が有名である。
ルートネットワークを手動で `igraph` オブジェクトに変換することはできるが、地理的な属性は失われる。
この **igraph** の制限を克服するために、路線ネットワークをグラフと地理的な線として同時に表現する **sfnetworks**\index{sfnetworks (package)} パッケージ [@R-sfnetworks] が開発された。
これは、グラフおよび地理的な線で表現し、以下に見るように tidy な文法である。
```{r 13-transport-23}
bristol_ways$lengths = st_length(bristol_ways)
ways_sfn = as_sfnetwork(bristol_ways)
class(ways_sfn)
```
```{r 13-transport-23-2, eval=FALSE}
ways_sfn
#> # A sfnetwork with 5728 nodes and 4915 edges
#> # A directed multigraph with 1013 components with spatially explicit edges
#> # Node Data: 5,728 × 1 (active)
#> # Edge Data: 4,915 × 7
#> from to highway maxspeed ref geometry lengths
#> <int> <int> <fct> <fct> <fct> <LINESTRING [°]> [m]
#> 1 1 2 road <NA> B3130 (-2.61 51.4, -2.61 51.4, -2.61 51.… 218.
#> # …
```
前のコードチャンクの出力 (スペースの関係上、最終的な出力は最も重要な 8 行のみを含むように短縮されている) は、`ways_sfn` がグラフ形式と空間形式の両方のノードとエッジを含む複合オブジェクトであることを表している。
`ways_sfn` は `sfnetwork` クラスで、 **igraph** パッケージの `igraph` クラスをベースにしている。
下の例では、各エッジを通る最短ルート\index{さいたんるーと@最短ルート}の数を意味する 'edge betweenness' \index{えっじ@エッジ} が計算されている (詳しくは `?igraph::betweenness` を参照)。
このデータセットに対して、エッジの間隔を計算した結果を図に示す。図には、比較のために `overline()` 関数で計算した自転車ルートネットワークデータセットをオーバーレイで表示している。
この結果は、グラフの各エッジがセグメントを表していることを示している。道路ネットワークの中心に近いセグメントは最も高い betweenness 値を持ち、一方、Bristol 中心部に近いセグメントはより高い自転車利用の可能性を持っていることが、これらの単純化されたデータセットに基づいて示されている。
```{r wayssln-gen}
ways_centrality = ways_sfn |>
activate("edges") |>
mutate(betweenness = tidygraph::centrality_edge_betweenness(lengths))
```
```{r wayssln, fig.cap="路線ネットワークデータセット。グレーの線は簡略化された道路網を表し、セグメントの太さは betweenness に比例する。緑色の線は、上記のコードで計算された潜在的な自転車利用フロー (片道) である。", fig.scap="A small route network.", dev="ragg_png"}
bb_wayssln = tmaptools::bb(route_network_scenario, xlim = c(0.1, 0.9), ylim = c(0.1, 0.6), relative = TRUE)
tm_shape(zones_od) +
tm_fill(fill_alpha = 0.2, lwd = 0.1) +
tm_shape(ways_centrality |> st_as_sf(), bb = bb_wayssln, is.main = TRUE) +
tm_lines(lwd = "betweenness",
lwd.scale = tm_scale(n = 2, values.scale = 2),
lwd.legend = tm_legend(title = "Betweenness"),
col = "#630032", col_alpha = 0.75) +
tm_shape(route_network_scenario) +
tm_lines(lwd = "bicycle",
lwd.scale = tm_scale(n = 2, values.scale = 2),
lwd.legend = tm_legend(title = "自転車トリップ数 (modeled, one direction)"),
col = "darkgreen", col_alpha = 0.75) +
tm_scalebar() + tm_layout(fontfamily = "HiraginoSans-W3")
```
```{r 13-transport-24, eval=FALSE, echo=FALSE}
# not producing groups of routes so removing for now...
# m = igraph::clusters(ways_sfn@g)
# igraph::V(ways_sfn@g)$m = m$membership
# gdf = igraph::as_long_data_frame(ways_sfn@g)
```
また、**sfnetworks** パッケージを用いると、このルートネットワークのグラフ表現を使って、出発地と目的地の間の最短ルート\index{さいたんるーと@最短ルート}を求めることができる。
<!-- TODO: make an exercise based on this if time allows (RL 2022-07) -->
このセクションで紹介した方法は比較的単純で、実際にはもっと可能なことはある。
**sfnetworks** が提供するグラフと空間の二つの機能により、多くの新しい強力な技法が可能になるが、このセクションで完全にカバーすることはできない。このセクションは、この分野のさらなる探求と研究のための強力な出発点を提供する。
上で使った例のデータセットが比較的小さい。
データのサブセットで手法をテストし、十分な RAM を確保することが助けになるが、R5 [@alessandretti_multimodal_2022] などの大規模ネットワークに最適化された交通ネットワーク分析ができる他のツールも調べる価値があるだろう。
## 新インフラの優先順位付け {#prioritizing-new-infrastructure}
この節では、交通計画分野においてジオコンピュテーションが政策関連の成果を作ることができることを示す。
持続可能な交通インフラの投資先として有望な場所を、教育目的のシンプルなアプローチで特定する。
本章で紹介するデータ駆動型アプローチの利点は、モジュール化されていることである。
この段階に至るまでには、(希望線から生成された)短いが車に依存する通勤経路を特定するための手順があり、(ルートネットワーク) セクションで **sfnetworks** パッケージを使用してルートネットワークの特性を分析することが含まれている。
本章の最後のコードチャンクは、自転車利用インフラから短い距離のエリアを表す新しいデータセットに、前のセクションの自転車利用潜在力の推定値を重ねることによって、これらの一連の分析を結合する。
この新しいデータセットは、以下のコードで作成される。(1) 交通ネットワークを表す `bristol_ways` オブジェクトから自転車道をフィルタする。(2) 自転車道の個々の線エンティティを単一の複合線オブジェクトに「統合」する (バッファ作成が速くなるため)。(3) 周囲に 100 m バッファのポリゴンを生成する。
```{r 13-transport-25}
existing_cycleways_buffer = bristol_ways |>
filter(highway == "cycleway") |> # 1) filter out cycleways
st_union() |> # 2) unite geometries
st_buffer(dist = 100) # 3) create buffer
```
次の段階は、ネットワークの中で、自転車利用の可能性が高いが、自転車利用のための設備がほとんどない点を表すデータセットを作成することである。
```{r, echo=FALSE, eval=FALSE}
waldo::compare(
sf::st_crs(route_network_scenario),
sf::st_crs(existing_cycleways_buffer)
)
```
```{r 13-transport-26, eval=FALSE}
route_network_no_infra = st_difference(
route_network_scenario,
route_network_scenario |> st_set_crs(st_crs(existing_cycleways_buffer)),
existing_cycleways_buffer
)
```
```{r 13-transport-26-workaround, echo=FALSE}
# TODO: remove this hidden chunk when rocker project updates PROJ version
route_network_no_infra = st_difference(
# route_network_scenario,
# Temporary workaround, see https://github.com/geocompx/geocompr/issues/863:
route_network_scenario |> st_set_crs(st_crs(existing_cycleways_buffer)),
existing_cycleways_buffer
)
```
Figure \@ref(fig:cycleways) は、自動車への依存度が高く、自転車の利用可能性が高いが、自転車専用道路が整備されていないルートを示している。
```{r 13-transport-28, eval=FALSE}
tmap_mode("view")
qtm(route_network_no_infra, basemaps = leaflet::providers$Esri.WorldTopoMap,
lines.lwd = 5)
```
```{r cycleways, echo=FALSE, message=FALSE, fig.cap="Bristol における自動車依存度を下げるために、自転車インフラを優先的に整備するルートの候補。静的マップは、既存のインフラと自動車と自転車の乗り換えの可能性が高いルートとの間のオーバーレイの概要を提供する (左)。`qtm()` 関数から生成されたインタラクティブ地図のスクリーンショットは、新しい自転車道から利益を得ることができる場所として Whiteladies Road を強調している (右)。", out.width="50%", fig.show='hold', fig.scap="Routes along which to prioritise cycle infrastructure.", fig.height=9, dev="ragg_png"}
# Previous verson:
# source("https://github.com/geocompx/geocompr/raw/main/code/13-cycleways.R")
tm_shape(existing_cycleways_buffer, bbox = bristol_region) +
tm_polygons(fill = "lightgreen") +
tm_shape(route_network_scenario) +
tm_lines(lwd = "bicycle",
lwd.scale = tm_scale(values.scale = 3),
lwd.legend = tm_legend(title = "自転車トリップ数 (モデル化、一方向)"),
position = tm_pos_out("center", "bottom"))
knitr::include_graphics("images/bristol_cycleways_zoomed.png")
```
この方法には限界がある。現実には、人々はゾーン重心に移動したり、特定のモードの最短ルート\index{さいたんるーと@最短ルート}アルゴリズムを常に使用するわけではない。
しかし、この結果は、自動車依存と公共交通の観点から、自転車専用道路を優先的に整備できるルートを示している。
この分析は、現実の交通計画の立案に使うためには、より大きなデータを使うなど、大幅に拡大して行う必要がある。
## 今後の方向性 {#future-directions-of-travel}
この章では、交通研究にジオコンピュテーションを利用する可能性を紹介し、オープンデータと再現可能なコードを用いて、都市の交通システムを構成するいくつかの重要な地理的要素を調査した。
この結果は、どこに投資が必要かを計画するのに役立つだろう。
交通システムは複数の相互作用レベルで機能しているため、ジオコンピュテーションの手法は交通システムの仕組みや異なる介入の効果を理解する上で大きな可能性を秘めている。
この分野でできることはまだまだたくさんある。この章で紹介した基礎の上に、さまざまな方向性を構築することが可能であろう。
交通は、多くの国で温室効果ガスの排出源として最も急速に増加しており、「特に先進国では最大の温室効果ガス排出部門」になると言われている ([EURACTIV.com](https://www.euractiv.com/section/agriculture-food/opinion/transport-needs-to-do-a-lot-more-to-fight-climate-change/) を参照)。
交通機関の排出量は社会全体で非常に不平等に配分されており、交通機関は (食料や暖房とは異なり) 幸福に不可欠なものではない。
需要の削減、車両の電化、徒歩や自転車などのアクティブな移動手段の導入により、このセクターが急速に脱炭素化する大きな可能性を秘めている。
新しいテクノロジーは、カーシェアリングを可能にすることで、車への依存度を下げることができる。
ドックレス型自転車や e スクーターのような「マイクロモビリティ」システムも出現し、General Bikeshare Feed Specification (GBFS) フォーマットの貴重なデータセットを作成し、[**gbfs**](https://github.com/simonpcouch/gbfs)パッケージで取り込んで処理することができるようになった。
こうした新しい交通などの変化は、人々が必要とする雇用やサービスの場所に到達する能力であるアクセシビリティに大きな影響を与える。そして、[**accessibility**](https://ipeagit.github.io/accessibility/) パッケージなどのパッケージを使用して、現在および変化のシナリオに基づいて定量化することが可能である。
こうした「交通の未来」を地域や国レベルでさらに探求することで、新たな知見を得られるだろう。
方法論的には、本章で示した基礎は、より多くの変数を分析に含めることで拡張することが可能である。
速度制限、交通量の多さ、自転車や歩行者用保護道の設置などのルートの特徴は、「モーダルスプリット」 (modal split、異なる交通手段によるトラベルの割合) に関連付けることができる。
例えば、OpenStreetMap\index{OpenStreetMap} のデータをバッファや、Chapter \@ref(attr) と Chapter \@ref(spatial-operations) で紹介した地理データ手法で集約すれば、交通ルートの近くに緑地があるかどうかを検出することも可能である。
R\index{R} の統計モデリング機能を使えば、例えば、現在と将来の自転車利用のレベルを予測することができるだろう。
この種の分析のベースには、Propensity to Cycle Tool (PCT)がある。 これは、R\index{R} で開発された一般にアクセス可能な ( [www.pct.bike](https://www.pct.bike/) 参照) 地図作成ツールで、イングランド全域の自転車利用への投資を優先させるために使用されている [@lovelace_propensity_2017]。
同様のツールは、世界中の大気汚染や公共交通機関へのアクセスなど、他のテーマに関連したエビデンスに基づく交通政策を奨励するためにも使用できる。
## 演習 {#ex-transport}
```{r, echo=FALSE, results='asis'}
res = knitr::knit_child('_13-ex-ja.Rmd', quiet = TRUE, options = list(include = FALSE, eval = FALSE))
cat(res, sep = '\n')
```