Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 在函数中获取过滤器以使用整洁的评估_R_Dplyr_Rlang - Fatal编程技术网

R 在函数中获取过滤器以使用整洁的评估

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

我尝试使用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 %>%
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