dplyr
パッケージはデータフレーム内の変数に対するベクトル演算(列方向)を行う場合には非常に有用なパッケージですが、行方向(列間)の演算を行うには少々不得手なところがあります。
Packages and Datasets
本ページではR version 3.4.4 (2018-03-15)の標準パッケージ以外に以下の追加パッケージを用いています。
Package | Version | Description |
---|---|---|
dplyr | 0.7.8 | A Grammar of Data Manipulation |
purrr | 0.2.5 | Functional Programming Tools |
purrrlyr | 0.0.3 | Tools at the Intersection of ‘purrr’ and ‘dplyr’ |
tibble | 1.4.2 | Simple Data Frames |
tidyr | 0.8.2 | Easily Tidy Data with ‘spread()’ and ‘gather()’ Functions |
tidyverse | 1.2.1 | Easily Install and Load the ‘Tidyverse’ |
また、本ページでは以下のデータセットを用いています。
Dataset | Package | Version | Description |
---|---|---|---|
iris | datasets | 3.4.4 | Edgar Anderson’s Iris Data |
行方向に計算する
例えば、iris
データセットの個体(行)ごとのSepal
(萼片)の合計値と平均値を求めたい場合、dplyr::mutate
関数を用いる場合、行ごとに処理するためにdplyr::rowwise
関数を併用して以下のように記述します。
iris %>%
dplyr::select(dplyr::starts_with("Sepal")) %>%
dplyr::rowwise() %>%
dplyr::mutate(sum = sum(Sepal.Length, Sepal.Width, na.rm = TRUE),
mean = mean(c(Sepal.Length, Sepal.Width), na.rm = TRUE)) %>%
head_tail()
Sepal.Length | Sepal.Width | sum | mean |
---|---|---|---|
5.1 | 3.5 | 8.6 | 4.3 |
4.9 | 3 | 7.9 | 3.95 |
4.7 | 3.2 | 7.9 | 3.95 |
… | … | … | … |
6.5 | 3 | 9.5 | 4.75 |
6.2 | 3.4 | 9.6 | 4.8 |
5.9 | 3 | 8.9 | 4.45 |
この場合は変数(列)が少ないのでコーディングは、さほど苦になりませんし処理的にも相応の速度なのですが、対象となる変数(列)が増えるとあまり効率的なコードとは言えなくなります。また、dplyr::rowwise
関数は将来的にディスコンになる可能性が高いので、今から覚える必然性もあまりなく、コードの保守性を考えても代替手段を利用すべきだと考えます。
purrr::mapを用いた計算方法
代替手段としては、本blogでも何度か登場しているpurrr
パッケージとtidyr
パッケージを利用します。tidyr::nest
関数で対象となる変数をリスト型にネストしてからpurrr::map
関数で処理します。これにより変数の数が増えても計算の方のコードを変更しなくても済みます。
iris %>%
dplyr::select(dplyr::starts_with("Sepal")) %>%
tibble::rowid_to_column("id") %>% # 行ごとに識別できるようにする
tidyr::nest(-id, .key = "data") %>% # 計算対象となる変数をネストする
dplyr::mutate(sum = purrr::map_dbl(data, ~ sum(unlist(.x), na.rm = TRUE)),
mean = purrr::map_dbl(data, ~ mean(unlist(.x), na.rm = TRUE))) %>%
tidyr::unnest() %>%
head_tail()
id | sum | mean | Sepal.Length | Sepal.Width | |
---|---|---|---|---|---|
1 | 1 | 8.6 | 4.3 | 5.1 | 3.5 |
2 | 2 | 7.9 | 3.95 | 4.9 | 3 |
3 | 3 | 7.9 | 3.95 | 4.7 | 3.2 |
… | … | … | … | … | … |
148 | 148 | 9.5 | 4.75 | 6.5 | 3 |
149 | 149 | 9.6 | 4.8 | 6.2 | 3.4 |
150 | 150 | 8.9 | 4.45 | 5.9 | 3 |
purrrlyrパッケージ
purrrlyr
パッケージはデータフレーム版purrr
と言えるパッケージで、行ごとに処理を適用する関数を持っています。purrr
パッケージを用いるよりコード的には分かりやすいとは思いますが、引数を指定する手間はdplyr::rowwaise
関数を用いる時と変わりません。また、purrrlyr
パッケージは開発が始まったばかりなので、今後、どのようになっていくか不透明なところがあります。
iris %>%
dplyr::select(dplyr::starts_with("Sepal")) %>%
purrrlyr::by_row(~ sum(.$Sepal.Length, .$Sepal.Width, na.rm = TRUE), .to ="sum") %>%
purrrlyr::by_row(~ mean(c(.$Sepal.Length, .$Sepal.Width), na.rm = TRUE), .to = "mean") %>%
tidyr::unnest() %>%
head_tail()
Sepal.Length | Sepal.Width | sum | mean |
---|---|---|---|
5.1 | 3.5 | 8.6 | 4.3 |
4.9 | 3 | 7.9 | 3.95 |
4.7 | 3.2 | 7.9 | 3.95 |
… | … | … | … |
6.5 | 3 | 9.5 | 4.75 |
6.2 | 3.4 | 9.6 | 4.8 |
5.9 | 3 | 8.9 | 4.45 |
Enjoy!