【问题标题】:Mutate a data frame in the tidyverse passed as a parameter in a function在函数中作为参数传递的 tidyverse 中改变数据帧
【发布时间】:2025-12-10 21:00:01
【问题描述】:

我正在尝试创建一个函数,您可以在其中传递数据框和其中一列的名称。在函数中,它应该改变数据框以创建您发送的列的缩放版本。这是我的尝试:

test_scale <- function(outcome, data){
  outcome_scaled = paste0(outcome, "_s")
  data = data %>% mutate(!!outcome_scaled := scale(as.numeric(outcome)))
  print(head(data[, outcome_scaled]))
}

但是,这不起作用,因为它只是打印我传递的任何结果的文本。

> test_scale("age", df)
mutate: new variable 'age_s' (character) with one unique value and 0% NA
[1] "age" "age" "age" "age" "age" "age"

如何获取outcome 的实际值,而不是传递的结果变量的字符串文本?

【问题讨论】:

  • 如果您包含一个简单的reproducible example,其中包含可用于测试和验证可能解决方案的示例输入和所需输出,则更容易为您提供帮助。不妨先查看dplyr.tidyverse.org/articles/programming.html 的示例。
  • 请问你dplyr的版本?
  • 这个问题的变体被问了很多,并得到了很多回答 - 为了与最新的 dplyr 语义保持一致,您需要类似 test_scale &lt;- function(outcome, data) { data %&gt;% mutate(across({{outcome}}, ~ scale(as.numeric(.x)), .names = "{col}_s")) }
  • 谁来编写包含任意 dplyr 代码并将其转换为任何最新 dplyr 语义的包?如果您必须将代码强制转换为数据框才能工作,则可以加分

标签: r dplyr tidyverse


【解决方案1】:

编辑

Ritchie Sacramento 在 cmets 中的答案更好;使用它。

--

这是一种可能的解决方案:

library(tidyverse)

test_scale <- function(outcome, data){
  outcome <- ensym(outcome)
  outcome_scaled = paste0(outcome, "_s")
  data2 = data %>% mutate(outcome_scaled := scale(as.numeric(!!outcome)))
  print(head(data2[, "outcome_scaled"]))
}
test_scale("Sepal.Length", iris)
#>            [,1]
#> [1,] -0.8976739
#> [2,] -1.1392005
#> [3,] -1.3807271
#> [4,] -1.5014904
#> [5,] -1.0184372
#> [6,] -0.5353840

使用ensym()表示你不一定需要引用“结果”:

test_scale(Sepal.Length, iris)
#>            [,1]
#> [1,] -0.8976739
#> [2,] -1.1392005
#> [3,] -1.3807271
#> [4,] -1.5014904
#> [5,] -1.0184372
#> [6,] -0.5353840

reprex package (v2.0.1) 于 2021-12-02 创建

【讨论】: