R中Curly Curly{{}}无法识别传入列名导致过滤失效问题
问题产生原因
{{}}(即Curly Curly语法)是tidyverse生态为自定义函数提供的元编程工具,仅支持接收不带引号的裸列名作为入参,自动完成数据列的环境注入,无法识别带引号的字符串形式列名。
你写的异常代码中,调用函数时给column参数传入的是字符串"Date",执行时{{column}}会直接取到这个字符串值参与比较,等价于运行filter("Date" >= "2022-04-01")。由于字符串"Date"的字典序始终大于传入的日期字符串,所有行都会被判定为符合过滤条件,因此返回结果和原始数据集行数完全一致,过滤逻辑不生效。
硬编码列名的版本能正常运行,是因为直接写Date时,dplyr会默认将其识别为数据集中的列,取列内存储的实际值和阈值做比较,逻辑符合预期。
修正方案
根据你希望的传参形式,二选一即可:
- 方案1:保留
{{}}语法,调用函数时传入不带引号的裸列名
library(tidyverse) test_data = tidyr::tribble( ~Date, ~Value, "2022-04-01", 5, "2022-04-02", 10, "2022-03-21", 15 ) censor_data = function(data,censor_date,column){ data %>% filter({{column}} >= censor_date) } result = censor_data( data = test_data, censor_date = "2022-04-01", column = Date # 传入裸列名,不要加引号 )
- 方案2:如果需要兼容传入字符串列名的用法,将
{{}}替换为.data[[ ]]数据代词
library(tidyverse) test_data = tidyr::tribble( ~Date, ~Value, "2022-04-01", 5, "2022-04-02", 10, "2022-03-21", 15 ) censor_data = function(data,censor_date,column){ data %>% # 用.data[[ ]]索引字符串形式的列名 filter(.data[[column]] >= censor_date) } result = censor_data( data = test_data, censor_date = "2022-04-01", column = "Date" # 传字符串列名可正常运行 )
补充提示:当前测试数据中的Date列是字符类型,做日期大小比较时建议提前用
as.Date()将列值和过滤阈值都转为标准Date类型,避免字符串字典序和日期实际顺序不一致导致的逻辑错误。
内容的提问来源于stack exchange,提问作者Tumaini Kilimba
相关产品推荐
相关产品推荐

