R 如何在列上使用tidyeval进行变异?
很抱歉造成混淆,但最终,我发布的第一个示例(在页面底部)没有帮助我了解tidyeval如何与mutate一起工作,因此我添加了一个新示例 我想创建一个包含三个参数的函数:R 如何在列上使用tidyeval进行变异?,r,dplyr,tidyeval,R,Dplyr,Tidyeval,很抱歉造成混淆,但最终,我发布的第一个示例(在页面底部)没有帮助我了解tidyeval如何与mutate一起工作,因此我添加了一个新示例 我想创建一个包含三个参数的函数: 数据帧 要变异的列 一个变量(来自数据帧),用于替换正在变异的值 例如,要将mpg中的值替换为carb中的值,我尝试了以下方法: I tried this colToX <- function(dt, ..., repl) { cols <- quos(...) repl <- quo(repl)
- 数据帧
- 要变异的列
- 一个变量(来自数据帧),用于替换正在变异的值
mpg
中的值替换为carb
中的值,我尝试了以下方法:
I tried this
colToX <- function(dt, ..., repl) {
cols <- quos(...)
repl <- quo(repl)
mutate_at(dt, vars(!!!cols), funs(function(x) !!repl))
}
colToX(mtcars, mpg, repl = carb)
错误:LHS必须是名称或字符串
最终,输出应该与mutate(mtcars,mpg=1)相同。因为错误是“error:LHS必须是一个名称或字符串”,其中LHS表示左手边,它具体指的是!!列:=1
部分。你需要将你制作的quosure转换成字符串或符号。使用quo\u name
colTo1 <- function(dt, ...) {
col <- quo_name(quo(...))
mutate(mtcars, !!col := 1)
}
colTo1@MrFlick的解决方案适用于单列情况,但由于OP使用了..
作为参数,我假设OP也希望函数能够容纳多个列。例如,以下操作不起作用:
colTo1 <- function(dt, ...) {
col <- quo_name(quo(...))
mutate(dt, !!col := 1)
}
colTo1(mtcars, mpg, cyl)
quos
将..
中的每个参数转换为quosure的向量。使用mutate_at
的vars
语法和显式拼接
从rlang
,我们可以在cols
中取消引用每个quosure,并在指定的列上进行变异
现在,它可以按预期工作:
colTo1(mtcars, mpg, cyl)
结果:
mpg cyl disp hp drat wt qsec vs am gear carb
1 1 1 160.0 110 3.90 2.620 16.46 0 1 4 4
2 1 1 160.0 110 3.90 2.875 17.02 0 1 4 4
3 1 1 108.0 93 3.85 2.320 18.61 1 1 4 1
4 1 1 258.0 110 3.08 3.215 19.44 1 0 3 1
5 1 1 360.0 175 3.15 3.440 17.02 0 0 3 2
6 1 1 225.0 105 2.76 3.460 20.22 1 0 3 1
7 1 1 360.0 245 3.21 3.570 15.84 0 0 3 4
8 1 1 146.7 62 3.69 3.190 20.00 1 0 4 2
9 1 1 140.8 95 3.92 3.150 22.90 1 0 4 2
10 1 1 167.6 123 3.92 3.440 18.30 1 0 4 4
...
mpg cyl disp hp drat wt qsec vs am gear carb
1 110 110 160.0 110 3.90 2.620 16.46 0 1 4 4
2 110 110 160.0 110 3.90 2.875 17.02 0 1 4 4
3 93 93 108.0 93 3.85 2.320 18.61 1 1 4 1
4 110 110 258.0 110 3.08 3.215 19.44 1 0 3 1
5 175 175 360.0 175 3.15 3.440 17.02 0 0 3 2
6 105 105 225.0 105 2.76 3.460 20.22 1 0 3 1
7 245 245 360.0 245 3.21 3.570 15.84 0 0 3 4
8 62 62 146.7 62 3.69 3.190 20.00 1 0 4 2
9 95 95 140.8 95 3.92 3.150 22.90 1 0 4 2
10 123 123 167.6 123 3.92 3.440 18.30 1 0 4 4
...
将“1
”作为另一个参数传递到函数中也很容易:
colToX <- function(dt, ..., X) {
cols <- quos(...)
mutate_at(dt, vars(!!!cols), function(x) x=X)
}
colToX(mtcars, mpg, cyl, X = 2)
在这里,我使用funs
函数创建一个函数调用列表,这些函数调用从vars
引用的每个列.data
是指在处将数据帧输入到mutate_中(在本例中为dt
)。我使用enquo
将调用的内容从X
转换为quosure,并使用将其解压缩代码>
结果:
mpg cyl disp hp drat wt qsec vs am gear carb
1 1 1 160.0 110 3.90 2.620 16.46 0 1 4 4
2 1 1 160.0 110 3.90 2.875 17.02 0 1 4 4
3 1 1 108.0 93 3.85 2.320 18.61 1 1 4 1
4 1 1 258.0 110 3.08 3.215 19.44 1 0 3 1
5 1 1 360.0 175 3.15 3.440 17.02 0 0 3 2
6 1 1 225.0 105 2.76 3.460 20.22 1 0 3 1
7 1 1 360.0 245 3.21 3.570 15.84 0 0 3 4
8 1 1 146.7 62 3.69 3.190 20.00 1 0 4 2
9 1 1 140.8 95 3.92 3.150 22.90 1 0 4 2
10 1 1 167.6 123 3.92 3.440 18.30 1 0 4 4
...
mpg cyl disp hp drat wt qsec vs am gear carb
1 110 110 160.0 110 3.90 2.620 16.46 0 1 4 4
2 110 110 160.0 110 3.90 2.875 17.02 0 1 4 4
3 93 93 108.0 93 3.85 2.320 18.61 1 1 4 1
4 110 110 258.0 110 3.08 3.215 19.44 1 0 3 1
5 175 175 360.0 175 3.15 3.440 17.02 0 0 3 2
6 105 105 225.0 105 2.76 3.460 20.22 1 0 3 1
7 245 245 360.0 245 3.21 3.570 15.84 0 0 3 4
8 62 62 146.7 62 3.69 3.190 20.00 1 0 4 2
9 95 95 140.8 95 3.92 3.150 22.90 1 0 4 2
10 123 123 167.6 123 3.92 3.440 18.30 1 0 4 4
...
OP可能还想更改mutate
调用中的硬编码mtcars
。@JakeKaupp是的,很抱歉这是一个打字错误,我应该用dt
替换它。我意识到我的示例对于我最初的问题有点有限,我需要在之后传递一个变量,而不是1:=
。你能概括一下那个案子吗?或者我应该发布一个新的问题…@Dambo更新了我的答案。看看这是否是你想要的。我的意思是能够通过类似于colToX(mtcars,mpg,cyl,X=mpg)
,其中mpg
是来自mtcars
@Dambo的变量。我编辑了我的答案,以解决你的“新”需求。一般来说,SO社区不赞成有一个初始问题,接受一个答案,改变原来的问题,然后拒绝接受接受的答案。因此,我建议下次提问时,提供回答者解决你“真实”问题所需的所有必要细节,尽量不要戏剧性地改变你的问题。我接受了asnwer,因为我最初是这么做的,但当我在mutate_impl(.data,dots)中运行你的新代码error时,我遇到了一个错误:计算错误:无效的下标类型“语言”代码>
mpg cyl disp hp drat wt qsec vs am gear carb
1 110 110 160.0 110 3.90 2.620 16.46 0 1 4 4
2 110 110 160.0 110 3.90 2.875 17.02 0 1 4 4
3 93 93 108.0 93 3.85 2.320 18.61 1 1 4 1
4 110 110 258.0 110 3.08 3.215 19.44 1 0 3 1
5 175 175 360.0 175 3.15 3.440 17.02 0 0 3 2
6 105 105 225.0 105 2.76 3.460 20.22 1 0 3 1
7 245 245 360.0 245 3.21 3.570 15.84 0 0 3 4
8 62 62 146.7 62 3.69 3.190 20.00 1 0 4 2
9 95 95 140.8 95 3.92 3.150 22.90 1 0 4 2
10 123 123 167.6 123 3.92 3.440 18.30 1 0 4 4
...