我想将不同的功能应用于小标题中的同一列。这些功能存储在字符串中。我曾经用mutate_
和这样的.dots
参数来做到这一点:
library(dplyr)
myfuns <- c(f1 = "a^2", f2 = "exp(a)", f3 = "sqrt(a)")
tibble(a = 1:3) %>%
mutate_(.dots = myfuns)
Run Code Online (Sandbox Code Playgroud)
这种方法仍然可以正常工作,但mutate_
不建议使用。我尝试使用mutate
和rlang
软件包获得相同的结果,但是距离还很远。
在我的实际示例中,myfuns
包含大约200个函数,因此不能一一键入。
提前致谢。
对于采用单一输入的简单方程,提供函数本身就足够了,例如
iris %>% mutate_at(vars(-Species), sqrt)
Run Code Online (Sandbox Code Playgroud)
或者,当使用方程而不是简单函数时,通过公式:
iris %>% mutate_at(vars(-Species), ~ . ^ 2)
Run Code Online (Sandbox Code Playgroud)
当使用访问多个变量的方程时,您需要使用 rlang quosures 代替:
area = quo(Sepal.Length * Sepal.Width)
iris %>% mutate(Sepal.Area = !! area)
Run Code Online (Sandbox Code Playgroud)
在这里,quo
创建一个“quosure” ——即你的方程的引用表示,与你使用字符串相同,除了与字符串不同的是,这个是正确的范围,可直接由 dplyr 使用,并且在概念上更清晰:它就像任何其他R 表达式,除非尚未评估。区别如下:
1 + 2
是一个带有 value 的表达式3
。quo(1 + 2)
是具有值的未计算的表达式1 + 2
该计算结果为 3
,但需要明确地评价。那么我们如何评估一个未评估的表达式呢?好 …:然后!!
(发音为“bang bang”) 取消引用先前引用的表达式,即评估它 -在 的上下文中mutate
。这很重要,因为Sepal.Length
和Sepal.Width
只在mutate
调用内部知道,而不是在调用外部知道。
在上述所有情况下,表达式也可以在列表中。唯一的区别是对于列表,您需要使用!!!
而不是!!
:
funs = list(
Sepal.Area = quo(Sepal.Length * Sepal.Width),
Sepal.Ratio = quo(Sepal.Length / Sepal.Width)
)
iris %>% mutate(!!! funs)
Run Code Online (Sandbox Code Playgroud)
该!!!
操作称为“取消引用拼接”。这个想法是它将其参数的列表元素“拼接”到父调用中。也就是说,它似乎修改了调用,就好像它包含逐字逐字的列表元素作为参数(不过,这仅适用于mutate
支持它的函数,例如)。
将字符串转换为表达式
myexprs <- purrr::map( myfuns, rlang::parse_expr )
Run Code Online (Sandbox Code Playgroud)
然后mutate
使用quasiquotation将这些表达式传递给正则:
tibble(a = 1:3) %>% mutate( !!!myexprs )
# # A tibble: 3 x 4
# a f1 f2 f3
# <int> <dbl> <dbl> <dbl>
# 1 1 1 2.72 1
# 2 2 4 7.39 1.41
# 3 3 9 20.1 1.73
Run Code Online (Sandbox Code Playgroud)
请注意,这也适用于涉及多列的字符串/表达式。
归档时间: |
|
查看次数: |
249 次 |
最近记录: |