由于您正在使用字符值动态构建变量名,因此更合理的做法是使用标准的数据框索引进行赋值,允许使用列名称的字符值。例如:
multipetal <- function(df, n) {
varname <- paste("petal", n , sep=".")
df[[varname]] <- with(df, Petal.Width * n)
df
}
使用mutate
函数,通过命名参数非常容易创建新列。但这假定您在键入命令时就已经知道了名称。如果您要动态指定列名,则还需要构建命名参数。
dplyr版本>=1.0
使用最新的dplyr版本,可以在使用:=
时使用来自glue
包的语法来命名参数。因此,在名称中使用{}
可以通过评估其中的表达式来获取值。
multipetal <- function(df, n) {
mutate(df, "petal.{n}" := Petal.Width * n)
}
如果您将列名传递给函数,您可以在字符串中以及列名中使用
{{}}
。
meanofcol <- function(df, col) {
mutate(df, "Mean of {{col}}" := mean({{col}}))
}
meanofcol(iris, Petal.Width)
dplyr版本 >= 0.7
dplyr
自版本0.7开始允许您使用:=
动态分配参数名称。您可以将函数编写为:
multipetal <- function(df, n) {
varname <- paste("petal", n , sep=".")
mutate(df, !!varname := Petal.Width * n)
}
欲了解更多信息,请参见可用于文档的vignette("programming", "dplyr")
。
dplyr (>=0.3 & <0.7)
dplyr
的稍早版本(>=0.3 <0.7)鼓励使用“标准评估”函数的替代方法。有关更多信息,请参见非标准评估vignette (vignette("nse")
)。
因此,在这里,答案是使用mutate_()
而不是mutate()
并执行:
multipetal <- function(df, n) {
varname <- paste("petal", n , sep=".")
varval <- lazyeval::interp(~Petal.Width * n, n=n)
mutate_(df, .dots= setNames(list(varval), varname))
}
dplyr < 0.3
请注意,早期版本的dplyr
也可以实现此操作。这需要仔细使用quote
和setName
:
multipetal <- function(df, n) {
varname <- paste("petal", n , sep=".")
pp <- c(quote(df), setNames(list(quote(Petal.Width * n)), varname))
do.call("mutate", pp)
}
mutate_
,而且从其他函数中也很难看出如何使用它。 - nacnudusquosure
等文件的内容。虽然上面的vignette链接不再有效,但是那个评论引导我找到了这篇总结,说的是关于tidyevaluation的:https://shipt.tech/https-shipt-tech-advanced-programming-and-non-standard-evaluation-with-dplyr-e043f89deb3d。我终于明白了!谢谢。 - Joshas.symbol
、substitute
等之上实现简洁的宏/元编程DSL。这些基本功能可能会很笨重和冗长。我喜欢他们所做的事情,但我真的不喜欢所有新术语、设计中的不断变化以及文档中过于复杂的描述,好像这是一件晦涩难懂的事情,人们不应该需要这样做。 - shadowtalker