mtcars |>
map(mean)$mpg
[1] 20.09062
$cyl
[1] 6.1875
$disp
[1] 230.7219
$hp
[1] 146.6875
$drat
[1] 3.596563
$wt
[1] 3.21725
$qsec
[1] 17.84875
$vs
[1] 0.4375
$am
[1] 0.40625
$gear
[1] 3.6875
$carb
[1] 2.8125
purrr(読み方は、「ぷりゃー」、「ぷるるる」等さまざま)パッケージは、Rの関数型プログラミングを支援するパッケージです。関数型プログラミングでは、関数を引数として渡すことで、複数の関数を組み合わせてプログラムを構築します。
purrrパッケージの利点の一つは、関数を繰り返し実行するコードを簡潔に書き換え可能な点です。例えば、以下のコードは、map()関数を使って、mtcarsデータセットの各列の平均値を計算しています。
$mpg
[1] 20.09062
$cyl
[1] 6.1875
$disp
[1] 230.7219
$hp
[1] 146.6875
$drat
[1] 3.596563
$wt
[1] 3.21725
$qsec
[1] 17.84875
$vs
[1] 0.4375
$am
[1] 0.40625
$gear
[1] 3.6875
$carb
[1] 2.8125
purrrを使わずに同様の処理を実行することももちろん可能です。しかしpurrrには、以下の表に示すようにたくさんの関数が用意されており、目的に応じて関数を使い分けることで、コードの保守性を高めることに貢献します。
| 与える引数の数 | 返り値がリスト | 返り値がベクトル | 返り値が入力と同じ型 | 返り値なし |
|---|---|---|---|---|
| 一つ | map() |
map_lgl(), map_chr(), map_dbl(), map_int(), map_vec() |
modify() |
walk() |
| 二つ | map2() |
map2_lgl(), map2_chr(), map2_dbl(), map2_int(), map2_vec() |
modify2() |
walk2() |
| 一つ + インデックス | imap() |
imap_lgl(), imap_chr(), imap_dbl(), imap_int() |
imodify() |
iwalk() |
| 任意 | pmap() |
pmap_lgl(), pmap_chr(), pmap_dbl(), pmap_int(), pmap_vec() |
- | pwalk() |
$x
[1] 2 4 6
| x |
|---|
| 2 |
| 4 |
| 6 |
1つ以上の変数を引数に与える関数を適用する場合、pmap()関数を使うと便利です。
Error in `map2()`:
! `.y` must be a vector, not a function.
[[1]]
[1] "aD"
[[2]]
[1] "bE"
[[3]]
[1] "cF"
dplyrパッケージのmutate()関数と組みあわせることで、ベクトル処理に対応していない関数であってもデータフレームの値に格納できます。
| x | y | z |
|---|---|---|
| a | D | aD |
| b | E | bE |
| c | F | cF |
tibble(
x = c("a", "b", "c"),
y = c("D", "E", "F")) %>%
mutate(z = pmap_chr(., \(x, y) paste0(x, y)))| x | y | z |
|---|---|---|
| a | D | aD |
| b | E | bE |
| c | F | cF |
tibble(
x = c("a", "b", "c"),
y = c("D", "E", "F")) %>%
mutate(z = pmap(., \(x, y) paste0(x, y))) |>
unnest(cols = z)| x | y | z |
|---|---|---|
| a | D | aD |
| b | E | bE |
| c | F | cF |
purrr 1.0.0からmap()関数の実行時に、処理状況を示すプログレスバーが表示されるようになっています。実行時間の長い処理を適用する際、全体のうちどの程度進んでいるのかがわかると安心です。これは.progress引数で制御します。
処理に失敗する要素の位置を特定できるようになっています。 これにより問題の検出と対応が素早く行えるようになります。
Error in `map()`:
ℹ In index: 3.
Caused by error in `x + 1`:
! non-numeric argument to binary operator
文字列、数値、論理値以外のベクトル化
[[1]]
[1] a
Levels: a
[[2]]
[1] b
Levels: b
[[3]]
[1] c
Levels: c