dplyr::acrossを使ってみる

Rでdata frameの特定の列に対してある処理を施すとき、私はdplyr::mutate_atdplyr::mutate_ifをよく使用している。 例えば、本来はnumeric型であるべき列がcharacter型となっているとき、それらの列を全てnumeric型に戻したいときがある。 以下は逆に、dplyr::mutate_ifを用いてnumeric型のものを全てcharacter型にする。

library(magrittr)

iris %>%
  dplyr::mutate_if(.predicate = is.numeric, as.character) %>%
  tibble::as_tibble()

# A tibble: 150 x 5
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
   <chr>        <chr>       <chr>        <chr>       <fct>  
 1 5.1          3.5         1.4          0.2         setosa 
 2 4.9          3           1.4          0.2         setosa 
 3 4.7          3.2         1.3          0.2         setosa 
 4 4.6          3.1         1.5          0.2         setosa 
 5 5            3.6         1.4          0.2         setosa 
 6 5.4          3.9         1.7          0.4         setosa 
 7 4.6          3.4         1.4          0.3         setosa 
 8 5            3.4         1.5          0.2         setosa 
 9 4.4          2.9         1.4          0.2         setosa 
10 4.9          3.1         1.5          0.1         setosa 
# … with 140 more rows

これを、dplyr::across関数を使うと、このように書ける。

iris %>%
  dplyr::mutate(dplyr::across(where(is.numeric), as.character)) %>%
  tibble::as_tibble()

# A tibble: 150 x 5
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
   <chr>        <chr>       <chr>        <chr>       <fct>  
 1 5.1          3.5         1.4          0.2         setosa 
 2 4.9          3           1.4          0.2         setosa 
 3 4.7          3.2         1.3          0.2         setosa 
 4 4.6          3.1         1.5          0.2         setosa 
 5 5            3.6         1.4          0.2         setosa 
 6 5.4          3.9         1.7          0.4         setosa 
 7 4.6          3.4         1.4          0.3         setosa 
 8 5            3.4         1.5          0.2         setosa 
 9 4.4          2.9         1.4          0.2         setosa 
10 4.9          3.1         1.5          0.1         setosa 
# … with 140 more rows

dplyr::across関数の第1引数として列を指定し、第2引数で処理内容を指定する使い方をするようだ。 今後はdplyr::hogehoge_if, atを使わず、dplyr::acrossを用いるのが推奨されるようだ。

(ちなみに私は、可読性が多少下がるかもしれないがpackage::functionの書き方が好みである。 どのパッケージのどの関数を使っているかを明示的にすること、それによって関数同士のconflictを避けることもできること、並列処理の際に多少楽になることが利点としてあげられる。 このあたりは別途記事にしてみたい)