-
Notifications
You must be signed in to change notification settings - Fork 0
/
shelter.qmd
395 lines (307 loc) · 16.8 KB
/
shelter.qmd
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
---
title: "オープンデータの活用"
---
オープンデータの取得から操作、可視化まで。
[徳島県オープンデータポータルサイト](https://opendata.pref.tokushima.lg.jp)から[緊急避難場所 (徳島県)](https://opendata.pref.tokushima.lg.jp/dataset/487.html)のデータをRで読み込み、処理します。
リンク先にはいくつかのデータがあります。ここでは「`洪水_登録データ一覧_2022年10月26日.csv (CSV 121KB)`」を例に解説を行います。
## 1. パッケージの読み込み
Rでは**パッケージ**と呼ばれる機能拡張をユーザーが自由に導入することが可能です。
パッケージの導入により、Rで実現可能な枠が広がります。
Rのインストール時に利用可能な、組み込みパッケージがありますが、これに加えていくつかのパッケージを導入しておくと、Rでの作業が快適になります。
パッケージの読み込みは`library({パッケージ名})`の形式で行います。
次のコードではいくつかのパッケージを読み込んでいます。
各パッケージがどのような機能をもつか、コメントとして示しました。
Rでは`#` 以降の文章はコメントとして扱われます。
コメントは、後からコードを見返した際、どのような処理をなぜ行ったのかを理解するのに役立つため、必要に応じて書いておくことが望ましいです。
```{r}
#| warning: false
#| message: false
library(readr) # 表形式データの読み込み
library(dplyr) # データ操作
library(ggplot2) # データ可視化
library(here) # ファイルの指定を容易にする
```
## 2. データの読み込み
データをRへ読み込むには、次に示す通り、いくつかの方法があります。
1. 対象ファイルを利用しているコンピュータのローカルディスクへ保存し、ファイルが置かれた場所(パス)を指定する
2. インターネット上に置かれたファイルのURLを指定する
3. RStudioのImport Dataset機能
ここでは、すでにデータが手元にあることを想定し、1の方法でデータを読み込みます。`read_csv()`関数のfile引数にデータが保存されているパスを指定しましょう。
パスの値を`file = "パス"`の形式で記述します。パスを引用符 `"` で囲む必要がある点に注意してください。
Rでは文字列を引用符で囲むルールが存在します。
また、locale引数にもファイル読み込みのためのオプションを指定し、コードを実行します。
```{r}
read_csv(here("data-raw/tksm_shelter_for_flood.csv"),
# 読み込みのオプション
# 日本語が使われる一部のファイルを読み込むと、文字化けをすることがあります。
# このファイルでも日本語が使われているため、次のオプションの指定で文字化けを回避します。
locale = locale(encoding = "SHIFT-JIS"))
```
Rでは処理の結果を再利用するために、オブジェクトを利用します。
読み込んだデータに対して、処理を加えるためにオブジェクトとして保存しましょう。
オブジェクトへの保存は「代入」とも呼ばれます。
代入は `<-` (代入演算子)の左側に保存先のオブジェクト名、右側に保存したい処理内容を記述して実行します。
```{r}
# 読み込んだcsvの内容を df_hinanjyo として記録する
df_hinanjyo <-
read_csv(here("data-raw/tksm_shelter_for_flood.csv"),
locale = locale(encoding = "SHIFT-JIS"))
```
オブジェクトに保存した内容(値)はいつでも呼び出すことができます。
```{r}
#| eval: false
#| echo: true
# コンソールでオブジェクト名を実行すると値が呼び出される
df_hinanjyo
```
読み込んだファイルのように、表形式で表現されるデータのことをRではデータフレームと呼びます。
データフレームは表計算ソフトのように1行1列それぞれに値が格納されています。
![洪水_登録データ一覧を表計算ソフトで表示した画面。Rでの読み込み結果が正しく行われていることを確認しましょう。](images/excel.png)
上記のようにオブジェクト名をコンソールで実行してデータフレームを表示することもできますが、
データフレームの中身を確認する関数はいくつかあります。
```{r}
#| eval: false
#| echo: true
View(df_hinanjyo)
```
```{r}
# データ中の各変数の値を縦方向に出力します
glimpse(df_hinanjyo)
```
::: {.callout-note}
インターネットが利用できない環境では、URLを指定したデータの読み込みが行えません。
ローカルディスクにファイルをダウンロードしておくことで、インターネット非接続状態でもファイルの読み込みが可能になります。
次のコマンドを実行するとファイルのダウンロード、ローカルでのパスを指定したファイルの読み込みが行われます。
```{r}
#| eval: false
#| echo: true
fs::dir_create(here("data-raw"))
# インターネット上のファイルをダウンロードする(ここではインターネット接続が必要です)
download.file("https://opendata.pref.tokushima.lg.jp/dataset/487/resource/6553/洪水_登録データ一覧_2022年10月26日_15時14分.csv",
# data-rawフォルダの中に tksm_shelter_for_flood.csv として保存します
here("data-raw/tksm_shelter_for_flood.csv"))
# 保存したcsvファイルのパスをfile引数で指定します
df_hinanjyo <-
read_csv(
file = here("data-raw/tksm_shelter_for_flood.csv"),
locale = locale(encoding = "SHIFT-JIS"))
```
![ダウンロードしたファイルとフォルダの関係](images/donwload_file.png)
:::
::: {.callout-note}
上記の処理はRStudioのFile import機能を使っても行えます。
この機能には、データの読み込み結果をプレビューできる、Rのコード入力を最低限に抑えることができるなどの利点があります。
![RStudioのImport dataset機能を使ったデータ読み込み](images/rstudio_import_dataset.png)
:::
## 3. データの操作・加工
データを読み込んだ後は自由自在にデータを操作したり加工を行うことができます。
以下に示すとおり、データ操作に便利な関数を提供するdplyrパッケージを使ってデータに変更を加えていきましょう。
- `select()`... 列の選択
- `filter()`... 行の絞り込み
- `mutate()`, `transmute()`... 値の編集
- `group_by()`, `summarise()` ... グループごとに値を集計する
- `arrange()`... 行の並び替え
- `count()`... 項目の頻度を数える
- `*_join()` ... データフレームの結合
データフレームを確認するとわかるように、このデータには複数の「写真」の列が存在します。
これらの列の中には値がありません。
値がない状態を「欠損」は呼ばれ、そのことを表現するために欠損値 (`NA`) が使われます。
こうした欠損値からなる列は不要と判断し、列を絞り込みましょう。
列の選択は`select()`関数で行います。この関数の引数に、残したい、または削除したい変数を記述して実行します[^1]。
関心のある列にデータを制限することで、データの見通しがよくなります。
[^1]: 列を削除するには、列名の前に`!`を付けて実行します。例) `select(df_hinanjyo, !c(`市町村`, `分類`))`
```{r}
df_hinanjyo <-
# 関心のある列を選び直す
select(df_hinanjyo,
`市町村`, `タイトル`, `所在地`, `緯度`, `経度`, `分類`)
glimpse(df_hinanjyo)
```
加えて、日本語の列名から英語での列名に変更します。
```{r}
# 緯度 ... latitude
# 経度 ... longitude
colnames(df_hinanjyo) <-
c("city", "title", "address", "latitude", "longitude", "type")
head(df_hinanjyo)
```
ここで`city`列に注目します。
この列は避難所の位置する市町村を記録すべき列ですが、いずれの行にも値は含まれません。
```{r}
# cityの項目を数える --> NA (欠損値)
count(df_hinanjyo, city)
```
```{r}
#| eval: false
#| echo: true
# 欠損値の行を確認
filter(df_hinanjyo, is.na(city))
# 欠損値でない行を確認
filter(df_hinanjyo, !is.na(city))
```
そこで避難所の住所を記録した`address`列の値から市町村名の部分だけを抜き出して、
`city`列を上書きすることを考えましょう。
`address`には`r df_hinanjyo$address[1]`のように住所が文字列として記録されています。
```{r}
# 1行目の住所を表示
df_hinanjyo$address[1]
# すべての住所を表示
# df_hinanjyo$address
# 県名を含む住所から市町村の部分を取り出す
stringr::str_extract(df_hinanjyo$address[1],
pattern = "(.{2}郡.{2,3}町|.{2,3}(市|町|村))")
```
```{r}
#| eval: false
#| echo: true
stringr::str_remove(df_hinanjyo$address[1], "徳島県")
stringr::str_extract(df_hinanjyo$address[1], ".{2}郡.{2,3}町")
x <-
which(is.na(stringr::str_extract(df_hinanjyo$address, "(.{2}郡.{2,3}町|.{2,3}(市|町|村))")))
df_hinanjyo$address[x]
```
すべての行にこの処理を適用しましょう。
`mutate()`関数を使って、任意の処理を各行へ適用可能です。
```{r}
df_hinanjyo <-
mutate(df_hinanjyo,
# 住所から市町村名の部分を取り出し、city列に格納する
city = stringr::str_extract(address, "(.{2}郡.{2,3}町|.{2,3}(市|町|村))"))
```
結果を確認します。
先ほど`count()`関数で`city`列の項目を数えた際には欠損値だけでしたが、
今度は市町村別の避難場所のカウントが正しく行われているように見えます。
```{r}
df_tokushima_hinanjyo_count <-
# sort = TRUE ... 市町村の項目が多い順(降順)に出力する
count(df_hinanjyo, city, sort = TRUE)
df_tokushima_hinanjyo_count
```
なお、この処理は`group_by()`関数と`summarise()`関数を組み合わせても実行できます。`group_by()`は指定した列の項目ごとにグループを作成し、グループに対する操作を可能にします。
`summarise()`関数はそうしたグループへの集計を行う際に利用します。
例えば、クラスで行った教科ごとの平均点を求める際、教科をグループとしてその平均値を求める、といった処理がこの2つの関数を組み合わせることで可能となります。
```{r}
#| eval: false
#| echo: true
# 下記と同じ結果を得る
# count(df_hinanjyo, city, sort = TRUE)
arrange(summarise(group_by(df_hinanjyo,
city),
n = n()),
desc(n))
```
グループ化した項目を数えるのに`n()`関数を使います。
このようなグループごとの項目の集計は頻繁に行う処理のため、ショートカットとして`count()`関数が用意されています。
```{r}
# いくつかの行は欠損値のまま
filter(df_tokushima_hinanjyo_count, is.na(city))
```
市町村別の避難場所の集計結果を見ると、三好市が最も数が多いことがわかります。
しかしこの値は人口や面積を考慮した値ではありません。
人口や面積の単位あたりの避難場所の数を比較することで、市町村別の評価が可能となります。
[グラフの作成](plot.html)で利用した[教育用標準データセット](https://www.nstac.go.jp/use/literacy/ssdse/)の中には、市区町村別の統計データを記録したものもあります。
データはすでにダウンロードされ、徳島県の市町村に関する情報が参照できる状態となっています。
次のコマンドを実行し、データをRに読み込みましょう。
```{r}
df_ssdse_a_tiny_tokushima <-
read_rds(here("data-raw/ssdse_a_tiny_tokushima.rds"))
df_ssdse_a_tiny_tokushima
```
dplyrパッケージではデータフレームを結合する関数`*_join()`を提供します。
関数の引数に対象となる2つのデータフレームを指定し、結合の際のキーとなる変数を引数byに与えて実行します。
```{r}
df_tokushima_hinanjyo_count <-
inner_join(
df_tokushima_hinanjyo_count,
df_ssdse_a_tiny_tokushima,
by = c("city" = "市区町村"))
df_tokushima_hinanjyo_count
```
`city`と`n`の2列からなるデータフレーム`df_tokushima_hinanjyo_count`に、`df_ssdse_a_tiny_tokushima`がもつ列の情報が加わったことがわかります。
追加された情報から、避難場所の数を単位当たり数を求めてみます。
```{r}
# 災害種別_洪水
df_tokushima_hinanjyo_count <-
transmute(df_tokushima_hinanjyo_count,
`市町村` = city,
`避難場所件数` = n,
`避難場所件数(人口1万人あたり)` = (n / `人口・世帯数_総人口`) * 10000)
df_tokushima_hinanjyo_count <-
# 人口1万人当たりの避難場所件数の順に並び替え
arrange(df_tokushima_hinanjyo_count,
desc(`避難場所件数(人口1万人あたり)`))
```
人口1万人あたりで見ても、三好市の避難場所件数が最も多いことに変わりはありませんでしたが、
勝浦川の流域に位置する勝浦町、上勝町が上位になりました。
## 4. グラフの作成
続いて、市町村別に避難場所の数を集計したデータ `df_tokushima_hinanjyo_count` をもとに、簡単なグラフを作成してみましょう。
避難場所の数(数量)を市町村で比較する際、適したグラフの種類は何でしょうか。
ここでは棒グラフと円グラフによるグラフ作成の例を示します。
```{r}
#| eval: true
#| echo: true
#| fig-cap: 徳島県内緊急避難場所(災害種別 洪水)の市町村別件数
#| label: shelter_count
p <-
ggplot(data = df_tokushima_hinanjyo_count,
aes(市町村, 避難場所件数)) +
# 棒グラフの指定
geom_bar(
stat = "identity", # n (市町村別の避難場所の数)が棒の高さに用いられる
fill = "#3F54B4" # 棒の塗りつぶしの色
)
p
```
`geom_bar()`関数を指定して棒グラフを描画しましたが、このグラフはいくつかの理由で情報を適切に伝えられていません。
例えば、
1. x軸の市町村の間隔が狭いために文字が潰れてしまっている
2. x軸の市町村の並びと避難場所の件数に関係がなく、関係を読み取りにくい
この問題を改善してみましょう。
まず、1の問題はx軸に複数の項目を並べる際に生じる問題です。
特に項目数が多い場合、横幅を広くとらないと文字が潰れてしまいます。
根本的な対策は、x軸とy軸を入れ替えて表示することです。
これにより、項目の間隔を気にする必要がなくなります(ただし高さを十分にする)。
すでに作成したグラフに対して、`coord_flip()`関数を適用するとx軸とy軸の入れ替えが行われます。
```{r}
#| eval: true
#| echo: true
#| fig-cap: 徳島県内緊急避難場所(災害種別 洪水)の市町村別件数(市町村別の並びを縦に変更)
#| label: shelter_count_coord_flip
#| fig-height: 6
p +
coord_flip()
```
続いて市町村名と避難場所の件数の関係をわかりやすく伝える工夫をしてみます。
現在の図は適当に市町村名が並んでいるように見えるため、避難場所の件数で入れ替えるようにします。
合わせてグラフ全体の見た目も調整しておきましょう。
```{r}
#| eval: true
#| echo: true
#| fig-cap: 徳島県内緊急避難場所(災害種別 洪水)の市町村別件数
#| label: shelter_count_coord_modify
#| fig-height: 6
p <-
ggplot(data = df_tokushima_hinanjyo_count,
aes(forcats::fct_reorder(市町村, 避難場所件数), 避難場所件数)) +
geom_bar(stat = "identity",
fill = "#3F54B4") +
coord_flip() +
xlab(NULL) +
ylab("避難場所の件数") +
labs(title = "徳島県内緊急避難場所(災害種別 洪水)の市町村別件数")
p
```
## 5. まとめ
:::{.callout-tip}
## 演習
1. 徳島県オープンデータポータルサイトから適当なデータを見つけ、ファイルをRに読み込みましょう。
2. 読み込んだデータをdplyrパッケージのデータ操作のための関数を使って処理してみましょう。
- `select()`
- `filter()`
- `mutate()`, `transmute()`
- `group_by()`, `summarise()`
- `arrange()`
- `count()`
- `*_join()`
などの関数が利用できます
:::