2 min read

two-dots ..1 (R)

Rstudioで予約語としてハイライトされる..1..2についてのメモ。

“double periods”とか“..1”とかでググってもまったく引っかからないが“two dots”だと多少は情報がある。 公式helpは??base::dotsで確認できる。

関数内で使う予約語で、two dotsを含む関数へ渡された引数を取ってくるためにある。 pipeを多用する{purrr}{dplyr}あたりと相性がいい。

例えば、..1を使うとpurrr::map_XXX()に投げた引数を内部で受け取ることができる。

library(purrr)
library(dplyr)

list_data <- 
  list(iris, cars)

1:2 %>%
  map(~ list_data[[.]] %>%
        mutate(., `index + 5th alphabet` = letters[..1 + 5]) %>%
        head(3))
## [[1]]
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
##   index + 5th alphabet
## 1                    f
## 2                    f
## 3                    f
## 
## [[2]]
##   speed dist index + 5th alphabet
## 1     4    2                    g
## 2     4   10                    g
## 3     7    4                    g

mutate()内のplaceholderにはpipe直前のlist_data[[.]]が渡され、..1には1フレーム上のmapに投げ込まれた値が渡されるイメージ。 ファイル名に情報を持つ複数のファイルを読み込むときに便利で、.idよりも汎用性が高い。 ただし可読性が下がるので多用はしないほうがよさそう。

裸で呼ぶとエラーになるので、括弧をつける。

1:2 %>%
  map(~ list_data[[.]] %>% mutate(., add_index = ..1) %>% head(3))
# > Error in mutate_impl(.data, dots) : Binding not found: ..1.
1:2 %>%
  map(~ list_data[[.]] %>% mutate(., add_index = (..1)) %>% head(3))
## [[1]]
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species add_index
## 1          5.1         3.5          1.4         0.2  setosa         1
## 2          4.9         3.0          1.4         0.2  setosa         1
## 3          4.7         3.2          1.3         0.2  setosa         1
## 
## [[2]]
##   speed dist add_index
## 1     4    2         2
## 2     4   10         2
## 3     7    4         2

実際には、readr::parse_number(), stringr::str_sub()あたりと併用するので問題となることはあまりない。