R 在函数中获取过滤器以使用整洁的评估
我尝试使用dplyr根据动态变量进行过滤 我发现要使过滤器工作,我需要将变量名括在括号中。但是,如果我将其编程为函数,它将无法正常工作R 在函数中获取过滤器以使用整洁的评估,r,dplyr,rlang,R,Dplyr,Rlang,我尝试使用dplyr根据动态变量进行过滤 我发现要使过滤器工作,我需要将变量名括在括号中。但是,如果我将其编程为函数,它将无法正常工作 df_ex <- data.frame(a = 1:10, b = 11:20) param <- quo(a) # returns df_ex with column a, only, as expected df_ex %>% dplyr::select(!!param) # returns expected df df_ex %&g
df_ex <- data.frame(a = 1:10, b = 11:20)
param <- quo(a)
# returns df_ex with column a, only, as expected
df_ex %>%
dplyr::select(!!param)
# returns expected df
df_ex %>%
dplyr::filter((!!param)==5)
# Now for the function
testfun <- function(test_df, filt_var){
filt_var_mod <- quo(filt_var)
test_df %>%
dplyr::filter((!!filt_var_mod)==5)
}
# returns empty df, not as expected
testfun(df_ex, "a")
df_ex%
dplyr::过滤器(!!参数)==5)
#现在开始函数
testfun如果您的函数接受列名作为字符,则无需引用它,另一方面,您需要将其转换为符号,并立即使用UQ
或在filter
函数中对其求值代码>在nse
语法中:
testfun <- function(test_df, filt_var){
test_df %>%
dplyr::filter((!!rlang::sym(filt_var)) == 5)
}
testfun(df_ex, "a")
# a b
#1 5 15
从技术上讲,对于此类问题,您不需要rlang、tidyeval、tibbles或dplyr,base R实际上不需要使用quote、eval、parse和其他自下而上的NSE工具
编辑:@thelatemail提出了更优雅的解决方案
为了好玩,data.table选项也可以:
library(data.table)
df_ex <- data.frame(a = 1:10, b = 11:20)
testfun <- function(test_df, filt_var) {
setDT(test_df,key = filt_var)[.(5)]
}
testfun(df_ex, "a")
有时,在生成简单函数时,可以使用作用域版本谓词代替tideval
例如,如果要在函数中以字符串形式传递名称,则可以选择filter\u at
下面是将变量作为字符串使用时在
处使用filter_的情况。传递要筛选的变量,然后在all\u vars
或any\u vars
中提供谓词函数。使用单个变量进行过滤时,使用哪一个变量并不重要
filter_at(df_ex, "a", all_vars(. == 5) )
a b
1 5 15
filter\u at
可轻松用于函数中
testfun = function(test_df, filt_var){
test_df %>%
dplyr::filter_at(filt_var, all_vars(. == 5) )
}
testfun(df_ex, "a")
a b
1 5 15
基本NSE似乎也起作用:
testfun2 <- function(test_df, filt_var){
filt_var_mod <- substitute(filt_var)
test_df %>%
dplyr::filter(eval(filt_var_mod) == 5)
}
testfun2(df_ex, a)
a b
1 5 15
testfun2或只是test\u df[test\u df[,filt\u var]==5,]
并取消所有这些求值、解析等。交互使用$
只是自找麻烦——fortunes::fortune(312)
Ha!这是一个简单得多的解决方案,我甚至不知道这是可能的!对于后来出现的任何人,df_-ex[它(eval(parse(text=paste0(“test_-df$”,filt_-var))==5),
是我在base-R函数的原始主体中包装的胡言乱语。是的,$
本质上只是[
的一个交互式快捷方式。而且,财富(106)
在这里是相关的—“如果答案是parse()你通常应该重新思考这个问题。”:-PI实际上非常喜欢提出的优雅的base R解决方案。然而,我很惊讶dplyr使这个问题变得如此复杂。
a b
1: 5 15
filter_at(df_ex, "a", all_vars(. == 5) )
a b
1 5 15
testfun = function(test_df, filt_var){
test_df %>%
dplyr::filter_at(filt_var, all_vars(. == 5) )
}
testfun(df_ex, "a")
a b
1 5 15
testfun2 <- function(test_df, filt_var){
filt_var_mod <- substitute(filt_var)
test_df %>%
dplyr::filter(eval(filt_var_mod) == 5)
}
testfun2(df_ex, a)
a b
1 5 15