让 quosures 在 map 调用中工作
Getting quosures to work inside a map call
我正在努力让 quosures 在 map
调用中工作。
一些玩具数据:
library(tidyverse)
df <- tibble(
g1 = letters[1:2] %>%
rep(each = 3),
g2 = letters[3:5] %>%
rep(times = 2),
y = runif(6)
)
我可以让这个函数工作,在我将它传递给 group_by
之前我 enquo
一个变量:
sum1 <- function(df, g){
g <- enquo(g)
df %>%
group_by(!! g) %>%
summarize(
mu = y %>%
mean
)
}
调用这个函数
sum1(df, g2)
让我得到了预期的结果。但是如果我想 map
多个分组变量,(即 g1
& g2
)
str_c("g", 1:2) %>%
map(
function(i)
sum1(df, i)
)
Returns错误
Error in grouped_df_impl(data, unname(vars), drop) :
Column `i` is unknown
如何在 map
通话中设置 quosures
?
我们可以使用group_by_at
,它可以接受一个字符串作为参数
library(tidyverse)
sum1 <- function(df, grps){
map(grps, ~
df %>%
group_by_at(.x) %>%
summarise(mu = mean(y))
)
}
sum1(df, str_c("g", 1:2))
#[[1]]
# A tibble: 2 x 2
# g1 mu
# <chr> <dbl>
#1 a 0.440
#2 b 0.469
#[[2]]
# A tibble: 3 x 2
# g2 mu
# <chr> <dbl>
#1 c 0.528
#2 d 0.592
#3 e 0.243
关于函数中带quosure的参数的用法,不清楚应该是单参数还是多参数
如果我们将字符串作为参数,将其转换为符号 (sym
) 然后计算 (!!
)
sum2 <- function(df, grps){
map(grps, ~
df %>%
group_by(!! rlang::sym(.x)) %>%
summarise(mu = mean(y))
)
}
sum2(df, str_c("g", 1:2))
#[[1]]
# A tibble: 2 x 2
# g1 mu
# <chr> <dbl>
#1 a 0.440
#2 b 0.469
#[[2]]
# A tibble: 3 x 2
# g2 mu
# <chr> <dbl>
#1 c 0.528
#2 d 0.592
#3 e 0.243
另一个有资格通过多个组的是
sum3 <- function(df, ...){
gs <- enquos(...)
map(gs, ~
df %>%
group_by(!! .x) %>%
summarise(mu = mean(y)))
}
sum3(df, g1, g2)
#[[1]]
# A tibble: 2 x 2
# g1 mu
# <chr> <dbl>
#1 a 0.440
#2 b 0.469
#[[2]]
# A tibble: 3 x 2
# g2 mu
# <chr> <dbl>
#1 c 0.528
#2 d 0.592
#3 e 0.243
str_c("g", 1:2) %>%
syms() %>%
map(sum1, df = df)
syms()
将 character
转换为符号(sum1
所期望的)。
将 map(function(i) sum1(df, i))
重写为 map(sum1, df = df)
可防止在 sum1
包含在另一个函数中时对承诺 i
进行不必要的评估。
将map(function(i) sum1(df, i))
重写为map(sum1, df = df)
允许将符号g1
和g2
直接传递给sum1()
,而不是符号i
.
(或者,str_c("g", 1:2) %>% syms() %>% map(function(i) sum1(df, !! i))
或 str_c("g", 1:2) %>% map(function(i) sum1(df, !! sym(i)))
工作,其中 !!
在将 i
传递给 sum1()
之前取消引号。
(实际上这有点过于简单化了:在 之前 不会发生取消引用,但是当你在 sum1
的正文中执行 enquo(g)
时)。
我正在努力让 quosures 在 map
调用中工作。
一些玩具数据:
library(tidyverse)
df <- tibble(
g1 = letters[1:2] %>%
rep(each = 3),
g2 = letters[3:5] %>%
rep(times = 2),
y = runif(6)
)
我可以让这个函数工作,在我将它传递给 group_by
之前我 enquo
一个变量:
sum1 <- function(df, g){
g <- enquo(g)
df %>%
group_by(!! g) %>%
summarize(
mu = y %>%
mean
)
}
调用这个函数
sum1(df, g2)
让我得到了预期的结果。但是如果我想 map
多个分组变量,(即 g1
& g2
)
str_c("g", 1:2) %>%
map(
function(i)
sum1(df, i)
)
Returns错误
Error in grouped_df_impl(data, unname(vars), drop) :
Column `i` is unknown
如何在 map
通话中设置 quosures
?
我们可以使用group_by_at
,它可以接受一个字符串作为参数
library(tidyverse)
sum1 <- function(df, grps){
map(grps, ~
df %>%
group_by_at(.x) %>%
summarise(mu = mean(y))
)
}
sum1(df, str_c("g", 1:2))
#[[1]]
# A tibble: 2 x 2
# g1 mu
# <chr> <dbl>
#1 a 0.440
#2 b 0.469
#[[2]]
# A tibble: 3 x 2
# g2 mu
# <chr> <dbl>
#1 c 0.528
#2 d 0.592
#3 e 0.243
关于函数中带quosure的参数的用法,不清楚应该是单参数还是多参数
如果我们将字符串作为参数,将其转换为符号 (sym
) 然后计算 (!!
)
sum2 <- function(df, grps){
map(grps, ~
df %>%
group_by(!! rlang::sym(.x)) %>%
summarise(mu = mean(y))
)
}
sum2(df, str_c("g", 1:2))
#[[1]]
# A tibble: 2 x 2
# g1 mu
# <chr> <dbl>
#1 a 0.440
#2 b 0.469
#[[2]]
# A tibble: 3 x 2
# g2 mu
# <chr> <dbl>
#1 c 0.528
#2 d 0.592
#3 e 0.243
另一个有资格通过多个组的是
sum3 <- function(df, ...){
gs <- enquos(...)
map(gs, ~
df %>%
group_by(!! .x) %>%
summarise(mu = mean(y)))
}
sum3(df, g1, g2)
#[[1]]
# A tibble: 2 x 2
# g1 mu
# <chr> <dbl>
#1 a 0.440
#2 b 0.469
#[[2]]
# A tibble: 3 x 2
# g2 mu
# <chr> <dbl>
#1 c 0.528
#2 d 0.592
#3 e 0.243
str_c("g", 1:2) %>%
syms() %>%
map(sum1, df = df)
syms()
将 character
转换为符号(sum1
所期望的)。
将 map(function(i) sum1(df, i))
重写为 map(sum1, df = df)
可防止在 sum1
包含在另一个函数中时对承诺 i
进行不必要的评估。
将map(function(i) sum1(df, i))
重写为map(sum1, df = df)
允许将符号g1
和g2
直接传递给sum1()
,而不是符号i
.
(或者,str_c("g", 1:2) %>% syms() %>% map(function(i) sum1(df, !! i))
或 str_c("g", 1:2) %>% map(function(i) sum1(df, !! sym(i)))
工作,其中 !!
在将 i
传递给 sum1()
之前取消引号。
(实际上这有点过于简单化了:在 之前 不会发生取消引用,但是当你在 sum1
的正文中执行 enquo(g)
时)。