Non standard evaluation from another function in R

后端 未结 3 1227
梦毁少年i
梦毁少年i 2021-02-02 12:38

Here is an example from Hadley\'s advanced R book:

sample_df <- data.frame(a = 1:5, b = 5:1, c = c(5, 3, 1, 4, 1))

subset2 <- function(x, condition) {
  c         


        
3条回答
  •  忘掉有多难
    2021-02-02 13:15

    In case anyone else stumbles upon this thread, here is the answer to task #5 below this section in Hadley's book. It also contains a possible general solution to the problem discussed above.

    subset2 <- function(x, condition, env = parent.frame()) {
      condition_call <- substitute(condition, env)
      r <- eval(condition_call, x, env)
      x[r, ]
    }
    scramble <- function(x) x[sample(nrow(x)), ]
    subscramble <- function(x, condition) {
      scramble(subset2(x, condition))
    }
    subscramble(sample_df, a >= 3)
    

    The magic happens in the second line of subset2. There, substitute receives an explicite env argument. From the help section for substitute: "substitute returns the parse tree for the (unevaluated) expression expr, substituting any variables bound in env." env "Defaults to the current evaluation environment". Instead, we use the calling environment.

    Check it out like this:

    debugonce(subset2)
    subscramble(sample_df, a >= 3)
    Browse[2]> substitute(condition)
    condition
    Browse[2]> substitute(condition, env)
    a >= 3
    

    I am not 100% certain about the explanation here. I think it just is the way substitute works. From the help page for substitute:

    Substitution takes place by examining each component of the parse tree as follows: (...) If it is a promise object, i.e., a formal argument to a function or explicitly created using delayedAssign(), the expression slot of the promise replaces the symbol. If it is an ordinary variable, its value is substituted (...).

    In the current environment, condition is a promise, so the expression slot is filled, and more importantly, condition_call receives a symbol as a value. In the calling environment, condition is just an ordinary variable, so the value (the expression) is substituted.

提交回复
热议问题