gpt4 book ai didi

r - dplyr tidyeval 相当于下划线函数版本

转载 作者:行者123 更新时间:2023-12-02 04:33:23 27 4
gpt4 key购买 nike

最新版本的 dplyr 不推荐使用下划线版本的函数,例如 filter_,转而使用 tidy evaluation .

新方式下划线形式的新形式是什么?如何使用 R CMD 检查来避免 undefined symbol ?

library(dplyr)

df <- data_frame(id = rep(c("a","b"), 3), val = 1:6)
df %>% filter_(~id == "a")

# want to avoid this, because it references column id in a variable-style
df %>% filter( id == "a" )

# option A
df %>% filter( UQ(rlang::sym("id")) == "a" )
# option B
df %>% filter( UQ(as.name("id")) == "a" )
# option C
df %>% filter( .data$id == "a" )

是否有首选或更考虑的形式?选项 C 是最短的,但在我的一些现实世界中较大的数据集和更复杂的 dplyr 结构上速度较慢:

microbenchmark(
sym = dsPClosest %>%
group_by(!!sym(dateVarName), !!sym("depth")) %>%
summarise(temperature = mean(!!sym("temperature"), na.rm = TRUE)
, moisture = mean(!!sym("moisture"), na.rm = TRUE)) %>%
ungroup()
,data = dsPClosest %>%
group_by(!!sym(dateVarName), .data$depth ) %>%
summarise(temperature = mean(.data$temperature , na.rm = TRUE)
, moisture = mean(.data$moisture , na.rm = TRUE)) %>%
ungroup()
,times=10
)
#Unit: milliseconds
# expr min lq mean median uq max neval
# sym 80.05512 84.97267 122.7513 94.79805 100.9679 392.1375 10
# data 4652.83104 4741.99165 5371.5448 5039.63307 5471.9261 7926.7648 10

还有一个answer for mutate_使用更复杂的语法。

最佳答案

根据您的评论,我猜应该是:

df %>% filter(!!as.name("id") == "a")

rlang 是不必要的,因为您可以使用 !!as.name 而不是 UQ 来完成此操作和sym

但也许更好的选择是范围过滤器,它可以避免与 quosure 相关的问题:

df %>% filter_at(vars("id"), all_vars(. == "a"))

在上面的代码中,vars() 确定我们要对哪些列应用过滤语句(在 filter_at 的帮助中,过滤语句称为“predicate”。在本例中,vars("id") 表示过滤语句仅应用于 id 列。过滤语句可以是 all_vars()any_vars() 语句,尽管它们在本例中是等效的。all_vars(.== "a") 表示所有vars("id") 中的列必须等于 "a"。是的,这有点令人困惑。

与您的示例类似的数据的计时:在本例中,我们使用 group_by_atsummarise_at,它们是这些函数的作用域版本:

set.seed(2)
df <- data_frame(group = sample(1:100,1e4*52,replace=TRUE),
id = rep(c(letters,LETTERS), 1e4),
val = sample(1:50,1e4*52,replace=TRUE))

microbenchmark(
quosure=df %>% group_by(!!as.name("group"), !!as.name("id")) %>%
summarise(val = mean(!!as.name("val"))),
data=df %>% group_by(.data$group, .data$id) %>%
summarise(val = mean(.data$val)),
scoped_group_by = df %>% group_by_at(vars("group","id")) %>%
summarise_at("val", mean), times=10)
Unit: milliseconds
expr min lq mean median uq max neval cld
quosure 59.29157 61.03928 64.39405 62.60126 67.93810 72.47615 10 a
data 391.22784 394.65636 419.24201 413.74683 425.11709 498.42660 10 b
scoped_group_by 69.57573 71.21068 78.26388 76.67216 82.89914 91.45061 10 a

原始答案

我认为在这种情况下,您可以输入过滤器变量作为裸名称,然后使用 enquo!! (相当于 UQ) 使用过滤器变量。例如:

library(dplyr)

fnc = function(data, filter_var, filter_value) {
filter_var=enquo(filter_var)
data %>% filter(!!filter_var == filter_value)
}

fnc(df, id, "a")
     id   val
1 a 1
2 a 3
3 a 5
fnc(mtcars, carb, 3)
   mpg cyl  disp  hp drat   wt qsec vs am gear carb 
1 16.4 8 275.8 180 3.07 4.07 17.4 0 0 3 3
2 17.3 8 275.8 180 3.07 3.73 17.6 0 0 3 3
3 15.2 8 275.8 180 3.07 3.78 18.0 0 0 3 3

关于r - dplyr tidyeval 相当于下划线函数版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47664611/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com