使用tidy eval与scales::rescale编写R语言自定义函数的问题
解决R语言tidy eval下scales::rescale的参数问题
你的核心问题是混淆了tidy eval中裸列名和字符串列名的处理逻辑:{{col}}(curly-curly操作符)是用来捕获未加引号的裸列名(比如调用函数时写resc(df, val)),如果你的col参数是带引号的字符串(比如"mpg"),{{col}}会直接把它当成字符串字面量,而非引用数据框中的列,自然无法正确取值。
针对你需要接收带引号字符串参数的需求,有两种可行方案:
方案1:直接使用.data代词(最简洁)
保持参数为字符串格式,用.data[[col]]引用目标列,这是你最初可行代码的延伸写法:
library(dplyr) library(scales) resc <- function(df, col){ df %>% mutate( rescaled_value = scales::rescale(.data[[col]], to = c(0, 1), from = range(.data[[col]], na.rm = TRUE)) ) }
注:给
range()加上na.rm=TRUE可以避免数据含NA值时出错;另外scales::rescale默认from参数就是range(x, na.rm=TRUE),所以实际可以省略from参数,和你最初的正确代码效果完全一致。
方案2:兼容裸列名和字符串参数
如果想让函数同时支持两种调用方式(resc(df, "val")和resc(df, val)),可以用ensym()将输入转换为符号,再用!!解引用:
library(dplyr) library(scales) resc <- function(df, col){ col_sym <- ensym(col) df %>% mutate( rescaled_value = scales::rescale(!!col_sym, to = c(0, 1), from = range(!!col_sym, na.rm = TRUE)) ) }
测试验证
# 生成测试数据 set.seed(123) df <- data.frame(val = sample(1:10, 5, replace = TRUE)) # 调用函数(方案2支持两种写法) resc(df, "val") # 或 resc(df, val)
内容的提问来源于stack exchange,提问作者Lenn
相关产品推荐
相关产品推荐

