R函数调用数据框变量报错‘cyl’未找到,求tidy eval解决方案
解决R代码中"cyl未找到"的错误及实现列值检查需求
问题根源
原代码的问题出在两点:
apply(MARGIN=2)的迭代环境和函数本身的环境不兼容,{{var}}这种tidy eval语法没法在apply里正确解析你传入的列参数,导致触发"cyl未找到"的错误。stopifnot的写法不符合apply的运行逻辑,根本没法实现检查指定列所有值的需求。
正确实现方案
方案一:用tidyverse风格实现(推荐)
借助dplyr的语法和tidy eval特性,直接定位指定列并检查所有值:
library(dplyr) check_percent_fun = function(df, var){ # 提取指定列的所有值 col_data = df %>% pull({{var}}) # 检查所有值是否大于0,不满足则报错 stopifnot("该列存在不大于0的值" = all(col_data > 0)) } # 正常测试(mtcars的cyl列全是正数,不会报错) check_percent_fun(mtcars, cyl) # 错误测试(构造包含负数的列,会触发报错) test_df = mtcars %>% mutate(cyl = c(-2, cyl[-1])) check_percent_fun(test_df, cyl)
方案二:基础R实现
如果不想依赖tidyverse包,用基础R语法也能实现:
check_percent_fun = function(df, var){ # 获取传入列的名称字符串 col_name = deparse(substitute(var)) # 提取列数据 col_data = df[[col_name]] # 检查是否存在<=0的值,存在则抛出错误 if(any(col_data <= 0)){ stop(paste0("列'", col_name, "'存在不大于0的值")) } } # 测试 check_percent_fun(mtcars, cyl)
代码说明
两种方案都是先精准提取你要检查的列,再判断列中是否存在不大于0的值:
- 方案一用
pull({{var}})完美适配tidy eval,all(col_data > 0)确保列中所有值都满足大于0的条件,stopifnot会自动在条件不成立时抛出你指定的错误信息。 - 方案二用
deparse(substitute(var))获取列名,再通过df[[col_name]]提取数据,用any(col_data <=0)快速判断是否有违规值,手动抛出更直观的错误提示。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

