在嵌套的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)
答案 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))
。