R自定义函数内使用rlang::sym报invalid argument type错误
报错核心原因
代码里三个写法直接导致报错和逻辑失效:
!!是rlang提供的非标准计算注入运算符,仅能在dplyr等支持tidy eval的函数的数据掩码上下文内生效,你在普通的if分支、match.fun调用外层直接写!!,R无法解析这个语法,直接触发invalid argument type报错。- 给传入的列名硬拼
df$前缀是完全多余的错误操作:rlang::sym()只需要接收裸列名字符串即可,拼完前缀后会被识别为名为df$qb_count的不存在变量,完全不符合dplyr的列引用规则。 - 提前在filter外部计算筛选条件,既脱离了数据掩码环境无法直接识别数据框列,计算出的结果也不是和数据框行数等长的逻辑向量,根本无法实现按行筛选。
修正方案
直接把筛选逻辑放到dplyr的filter内部做注入即可,不需要硬拼字符串:
library(tidyverse) library(rlang) custom_filter <- function( df, pos_filter_1 = NULL, ct_filter_1, filter_1 ){ # 未指定筛选列时直接返回原数据 if (is.null(pos_filter_1)) return(df) # 将字符串列名转为符号后注入filter表达式,在数据掩码内完成比较运算 fin_df <- df %>% dplyr::filter( match.fun(filter_1)(!!rlang::sym(pos_filter_1), ct_filter_1) ) return(fin_df) }
验证测试
用提供的复现示例运行:
df <- tibble(x1 = letters[1:9], qb_count = 1:9, rb_count = 10:18) custom_filter(df, 'qb_count', 5, "<=")
可以正常得到筛选结果,返回qb_count小于等于5的行:
# A tibble: 5 × 3 x1 qb_count rb_count <chr> <int> <int> 1 a 1 10 2 b 2 11 3 c 3 12 4 d 4 13 5 e 5 14
补充:如果后续要扩展支持多条件动态筛选,可以把每个筛选条件封装成单独的表达式存在列表里,用
!!!批量注入到filter中即可,不要在filter外部提前计算筛选逻辑值。
内容的提问来源于stack exchange,提问作者Sam Hoppen
相关产品推荐
相关产品推荐

