R:具有嵌套函数的非标准评估

时间:2019-03-02 19:48:06

标签: r

我在数据帧上有一个函数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

2 个答案:

答案 0 :(得分:0)

最简单的方法是使用rlangtidyverse函数与准引号兼容:

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