使用%>%管道和点(.)表示法

joh*_*nes 22 r magrittr

map嵌套的data_frame上使用时,我不明白为什么后两个版本会出错,我应该如何使用dot(.)?

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)
Run Code Online (Sandbox Code Playgroud)

Axe*_*man 30

问题不是map,而是%>%管道如何处理..考虑以下示例(请记住,这/是R中的两个参数函数):

简单的管道:

1 %>% `/`(2)
Run Code Online (Sandbox Code Playgroud)

相当于`/`(1, 2)1 / 2给出0.5.

.使用简单:

1 %>% `/`(2, .)
Run Code Online (Sandbox Code Playgroud)

相当于`/`(2, 1)2 / 1给出2.

您可以看到它1不再用作第一个参数,而只是作为第二个参数.

其他.用途:

但是,当子集化时,这不起作用.:

list(a = 1) %>% `/`(.$a, 2)
Run Code Online (Sandbox Code Playgroud)
Error in `/`(., .$a, 2) : operator needs one or two arguments
Run Code Online (Sandbox Code Playgroud)

我们可以看到.两次注入,作为第一个参数并在第二个参数中进行了子集化.像这样的表达式.$a有时被称为嵌套函数调用(该$函数在/函数内部使用,在本例中).

我们使用大括号来避免第一次参数注入:

list(a = 1) %>% { `/`(.$a, 2) }
Run Code Online (Sandbox Code Playgroud)

再次给出0.5.

实际问题:

你实际上在呼唤map(df, df$data, min),而不是map(df$data, min).

解:

使用大括号:

df %>% { map(.$data, min) }
Run Code Online (Sandbox Code Playgroud)

另请参阅标题使用点作为次要用途,?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)).