使用dplyr编写函数创建新列:推荐的元编程运算符用法
在dplyr中创建新列:拥抱运算符
{{}} vs !!运算符的推荐实践 核心结论
推荐优先使用拥抱运算符{{}},这是tidyverse团队在现代dplyr元编程中主推的简化语法,完全替代了旧版enquo()+!!的组合写法。
两种方式的关键差异
{{}}是enquo()(捕获用户输入的表达式)+!!(反引用表达式)的语法糖,自动完成了元编程的核心两步操作,无需手动调用enquo()。- 从你的示例代码可以看到,使用
{{}}的add_col1支持两种更灵活的调用方式:- 带引号的列名字符串:
add_col1(cars, "new_col") - 裸名(无引号)形式:
add_col1(cars, new_col)
这完全贴合dplyr一贯的用户友好设计,让用户可以按自己的习惯选择调用方式。
- 带引号的列名字符串:
- 而依赖
!!的add_col2,如果没有提前用enquo()捕获输入表达式,就无法处理裸名调用,必须强制传入带引号的字符串,灵活性大打折扣——这也是你示例中add_col2(cars, new_col)失败的原因。
!!的适用场景
虽然{{}}是常规场景的首选,但!!并非完全被淘汰:当你需要手动控制引用逻辑时(比如提前捕获表达式并存储到变量中,或者需要动态组合多个复杂表达式),!!依然有用。例如:
add_col3 <- function(data, col_name) { # 手动捕获表达式 col_expr <- enquo(col_name) data |> dplyr::mutate(!!col_expr := "new") }
但这种写法已经被{{}}简化,日常场景下完全没必要多此一举。
总结
- 编写常规的dplyr风格函数时,优先使用
{{}},它更简洁、更符合tidyverse的设计理念,还能兼容多种调用方式。 - 仅在复杂元编程场景(需要手动管理引用的表达式)时,才考虑结合
enquo()和!!。
内容的提问来源于stack exchange,提问作者MoltenLight
相关产品推荐
相关产品推荐

