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

时间:2017-02-22 07:19:11

标签: r magrittr

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

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)

1 个答案:

答案 0 :(得分:24)

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

简单的管道:

1 %>% `/`(2)

等同于`/`(1, 2)1 / 2,并提供0.5

简单.使用:

1 %>% `/`(2, .)

等同于`/`(2, 1)2 / 1,并提供2

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

其他.使用:

但在对.进行子集化时

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

我们可以看到.被注入两次,作为第一个参数并在第二个参数中进行了子集化。像.$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))