web-dev-qa-db-ja.com

%>%パイプ、およびドット(。)表記を使用する

ネストされた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)
24
johannes

問題は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))と同等です。

32
Axeman