【问题标题】:R: non-standard evaluation with nested functionsR:具有嵌套函数的非标准评估
【发布时间】:2019-03-02 19:48:05
【问题描述】:

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

【问题讨论】:

    标签: r


    【解决方案1】:

    最简单的方法是使用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
    # ...
    

    【讨论】:

      【解决方案2】:

      使用较新版本的rlang0.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
      

      【讨论】:

        猜你喜欢
        • 2016-04-27
        • 1970-01-01
        • 1970-01-01
        • 2016-09-18
        • 1970-01-01
        • 2019-03-23
        • 2018-07-28
        • 2019-09-18
        • 2018-08-01
        相关资源
        最近更新 更多