ネストされたdata_frameでmap
を使用する場合、後者の2つのバージョンでエラーが発生する理由がわかりません。ドット(.
)?
library(tidyverse)
# dummy data
df <- tibble(id = rep(1:10, each = 10),
val = runif(100))
df <- nest(df, -id)
# works as expected
map(df$data, min)
df %>% .$data %>% map(., min)
# gives an error
df %>% map(.$data, min)
# Error: Don't know how to index with object of type list at level 1
df %>% map(data, min)
問題はmap
ではなく、%>%
パイプが.
をどのように処理するかです。次の例を検討してください(/
はRの2つの引数関数であることを忘れないでください)。
1 %>% `/`(2)
`/`(1, 2)
または1 / 2
と同等であり、0.5
を提供します。
.
の使用:1 %>% `/`(2, .)
`/`(2, 1)
または2 / 1
と同等であり、2
を提供します。
1
が最初の引数として使用されなくなり、2番目の引数としてのみ使用されていることがわかります。
.
の使用:ただし、これは機能しません.
をサブセット化する場合:
list(a = 1) %>% `/`(.$a, 2)
Error in `/`(., .$a, 2) : operator needs one or two arguments
.
が最初の引数として2回挿入され、2番目の引数にサブセット化されていることがわかります。 .$a
のような式は、ネストされた関数呼び出しと呼ばれることもあります(この場合、$
関数は/
関数内で使用されます)。
最初の引数の挿入を避けるために中括弧を使用します。
list(a = 1) %>% { `/`(.$a, 2) }
再び0.5を与えます。
実際には、map(df, df$data, min)
ではなくmap(df$data, min)
を呼び出しています。
中括弧を使用します。
df %>% { map(.$data, min) }
?magrittr::`%>%`
のヘッダー二次的な目的でドットを使用するも参照してください。
特に、プレースホルダーがネストされた関数呼び出しでのみ使用される場合、lhsも最初の引数として配置されます!これは、ほとんどのユースケースで、これが最も読みやすいコードを生成するためです。たとえば、
iris %>% subset(1:nrow(.) %% 2 == 0)
はiris %>% subset(., 1:nrow(.) %% 2 == 0)
と同等ですが、少しコンパクトです。 rhsを中括弧で囲むことにより、この動作を無効にすることができます。たとえば、1:10 %>% {c(min(.), max(.))}
はc(min(1:10), max(1:10))
と同等です。