我在数据帧上有一个函数f1,该函数调用另一个函数f2,然后对f2的输出进行填充。 f2本身可以交互工作,但是当f1调用它时如何使它运行?
f1 <- function(x, y) {
z <- f2(x, y)
# do stuff with z
w <- z
return(w)
}
f2使用subset()取消选择某些列:
f2 <- function(x, y) {
y <- substitute(y)
subset(x, select = -eval(y))
}
如您所见,f2可以交互工作。我不在乎,但是我确实希望它在被f1调用时能够正常工作。
# This works fine interactively (but I don't care about that)
f2(mtcars,mpg)
# This is what I want to work
f1(mtcars,mpg)
Error in -eval(y) : invalid argument to unary operator
我不希望更改f1或其参数。如何重新编写f2,使其在f1中正常工作?
这里有一个类似的问题,我无法将其应用于上下文:R: passing expression to an inner function
答案 0 :(得分:0)
最简单的方法是使用rlang
和tidyverse
函数与准引号兼容:
library(dplyr)
library(rlang)
f1 <- function(x, y) {
z <- f2(x, -!!enquo(y))
# do stuff with z
w <- z
return(w)
}
f2 <- function(x, y) {
select(x, !!enquo(y))
}
f1(mtcars,mpg)
# cyl disp hp drat wt qsec vs am gear carb
# Mazda RX4 6 160.0 110 3.90 2.620 16.46 0 1 4 4
# Mazda RX4 Wag 6 160.0 110 3.90 2.875 17.02 0 1 4 4
# Datsun 710 4 108.0 93 3.85 2.320 18.61 1 1 4 1
# ...
这在R底下有效:
f1 <- function(x, y) {
z <- f2(x, substitute(y))
# do stuff with z
w <- z
return(w)
}
f2 <- function(x, y) {
eval(substitute(subset(x, select = -Y), list(Y = y)))
}
f1(mtcars,mpg)
# cyl disp hp drat wt qsec vs am gear carb
# Mazda RX4 6 160.0 110 3.90 2.620 16.46 0 1 4 4
# Mazda RX4 Wag 6 160.0 110 3.90 2.875 17.02 0 1 4 4
# Datsun 710 4 108.0 93 3.85 2.320 18.61 1 1 4 1
# ...
答案 1 :(得分:0)
使用rlang
0.4.0
的较新版本,我们可以使用{{...}}
(卷曲)来简化评估工作
library(rlang)
f1 <- function(x, y) {
z <- f2(x, -{{y}})
# do stuff with z
w <- z
return(w)
}
f2 <- function(x, y) {
select(x, {{y}})
}
f1(mtcars,mpg) %>%
head
# cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 6 160 110 3.90 2.620 16.46 0 1 4 4
#Mazda RX4 Wag 6 160 110 3.90 2.875 17.02 0 1 4 4
#Datsun 710 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 8 360 175 3.15 3.440 17.02 0 0 3 2
#Valiant 6 225 105 2.76 3.460 20.22 1 0 3 1