如何从mutate_()迁移至tidy evaluation?是否需通过函数实现?
mutate_() to Tidy Evaluation: A Practical Guide Great question! Making the switch from old underscore-style functions like mutate_() to tidy evaluation is a smart move—once you get familiar with the syntax, it’s far more intuitive and flexible for dynamic data manipulation. Let’s walk through how to make this transition, and address whether functions are the right approach here.
Basic Replacement: Simple Mutations
First, let’s cover the most common case: replacing a straightforward mutate_() call with modern tidy evaluation.
Old mutate_() Syntax
If you were writing something like this (using formulas or strings to define columns):
# Using formulas mutate_(my_data, new_col = ~old_col + 1) # Using strings (less common but still used) mutate_(my_data, "new_col" = "old_col + 1")
Modern Tidy Evaluation Syntax
You can now write this directly with mutate()—no underscore needed, and you can use plain R expressions:
mutate(my_data, new_col = old_col + 1)
This works because dplyr now uses tidy evaluation to automatically capture and evaluate the expressions you pass.
Dynamic Column Names & Batch Mutations
Your question mentions passing a list of new variables and their creation logic—this is where tidy evaluation really shines. Let’s break down how to replicate that workflow.
Old .dots Approach
Previously, you might have used the .dots parameter to pass a list of formulas/strings:
var_specs <- list( sum_ab = ~a + b, prod_ab = ~a * b, diff_ab = ~a - b ) mutate_(my_data, .dots = var_specs)
Modern Unquoting with !!!
With tidy evaluation, you can use the unquote-splice operator (!!!) to pass your list of expressions directly to mutate():
library(dplyr) library(rlang) # For quosure helpers, though dplyr loads most of these now var_specs <- list( sum_ab = ~a + b, prod_ab = ~a * b, diff_ab = ~a - b ) mutate(my_data, !!!var_specs)
The !!! tells dplyr to "unpack" the list and treat each element as a separate argument to mutate().
Dynamic Column Names (Strings)
If your new variable names are stored as strings (instead of being named in the list), use sym() to convert them to symbols, and := (the "named unquote" operator) to assign them:
var_names <- c("sum_ab", "prod_ab") var_exprs <- list(~a + b, ~a * b) # Combine names and expressions into a named list named_specs <- set_names(var_exprs, var_names) mutate(my_data, !!!named_specs) # Or do it inline mutate(my_data, !!sym(var_names[1]) := a + b, !!sym(var_names[2]) := a * b)
You can also use the curly-curly operator ({{ }}) as a simpler shorthand if you’re working with function arguments (more on that below).
Should You Use Functions for This?
Absolutely—this is exactly the kind of scenario where wrapping your logic in a custom function makes sense. Tidy evaluation was designed to make it easy to write reusable, dynamic functions that work seamlessly with dplyr.
Example Custom Function
Let’s build a function that takes a dataset and a list of variable specifications, then returns the dataset with the new columns added:
add_custom_columns <- function(data, specs) { # specs is a named list where names = new column names, values = expressions mutate(data, !!!specs) } # Usage my_data <- tibble(a = 1:5, b = 6:10) my_specs <- list( sum_ab = a + b, # You can even skip the ~ now! prod_ab = a * b, avg_ab = (a + b)/2 ) add_custom_columns(my_data, my_specs)
Even More Flexible: Accepting Direct Expressions
If you want users to pass the column definitions directly as arguments (like they would with mutate()), use enquos() to capture the expressions:
add_custom_columns <- function(data, ...) { # Capture all the expressions passed via ... new_vars <- enquos(...) mutate(data, !!!new_vars) } # Usage (just like regular mutate!) add_custom_columns(my_data, sum_ab = a + b, prod_ab = a * b, avg_ab = (a + b)/2 )
This makes your function feel just like a native dplyr function, which is super intuitive for other tidyverse users.
Key Takeaways
- Replace
mutate_()with plainmutate()for static mutations—no extra syntax needed. - Use
!!!to splice lists of expressions intomutate()for batch operations. - Use
sym()+:=or{{ }}for dynamic column names. - Wrapping this logic in a function is highly recommended—it makes your code reusable, testable, and easier to maintain.
内容的提问来源于stack exchange,提问作者kputschko

