内部函数从外部函数拉取调用并导致错误

时间:2017-01-26 10:01:21

标签: r scope

我正在使用库中的一个函数跳跃到另一个函数中。最后两行的跳跃函数是:

rval$call <- sys.call(sys.parent())
rval

这显然会导致对外部函数的调用传递给rval$call。以后需要实际调用regsubsets函数作为参数。

下面举例说明:

library(leaps)
#Create some sample data to perform a regression on
inda <- rnorm(100)
indb <- rnorm(100)
dep <- 2 + 0.1*inda + 0.2*indb + rnorm(100, sd = 0.3)
dfk <- data.frame(dep=dep, inda = inda, indb = indb)

#Create some arbitrary outer function
test <-  function(dependent, data){
  best.fit <- regsubsets(as.formula(paste0(dependent, " ~ .")), data = data, nvmax = 2)
  return(best.fit)
}
#Call outer function
best <- test("dep", dfk)
best$call #Returns "test("dep", dfk)"

所以best$call将包含对外部函数(test)的调用,而不是对内部(regsubsets)函数的调用。因为它不是真正改变内部功能的选择,有没有办法避免这个问题?

编辑:

解决问题的方法可能是这样的:

test <-  function(dependent, data){
  thecall <- 'regsubsets(as.formula(paste0(dependent, " ~ .")), data = data, nvmax = 2)'
  best.fit <- eval(parse(text = thecall))
  #best.fit$call <- [some transformation of thecall
  return(best.fit)
}

EDIT2:     我需要访问$ call里面的内容的原因是我需要在一个预测函数中将其从简介复制到统计学习中:

predict.regsubsets <- function(regsubset_model, newdata, id, ...){
  form <- as.formula(regsubset_model$call[[2]])
  mat <- model.matrix(form, newdata)
  coefi <- coef(regsubset_model, id = id)
  xvars <- names(coefi)
  mat[, xvars] %*% coefi
}

在第二行,它使用$ call

1 个答案:

答案 0 :(得分:1)

我还不完全清楚如何使用它,但对于test函数,你可以编写以下代码:

test = function (dependent, data) {
    regsubsets_call = bquote(regsubsets(.(as.formula(paste0(dependent, " ~ ."))),
                                        data = .(substitute(data)), nvmax = 2))
    best_fit = eval(regsubsets_call)
    best_fit$call = regsubsets_call
    best_fit
}

但是,结果可能不适用于程序包提供的下游功能(但实际上,它可能会;我猜summary.regsubsets仅使用它来打印调用)。

这里发生了什么?

bquote构建一个未评估的R表达式;它与quote类似,但它允许您插值(类似于substitute)。 substitute(data)意味着,不是将实际的data.frame放入调用(这将导致非常笨拙的输出,而是将用户传递的变量名称(或表达式)放到test。因此,如果用户将其称为test('mpg', mtcars),则生成的表达式将为

regsubsets(mpg ~ ., data = mtcars, nvmax = 2)    

然后(a)通过eval评估生成的调用对象,并将(b)存储在生成的$call中。

顺便说一句,公式可以(并且,就我而言,应该)以相同的方式构建;无需解析字符串:

as.formula(bquote(.(as.name(dependent)) ~ .))
总而言之,整个表达将成为:

formula = as.formula(bquote(.(as.name(dependent)) ~ .))
regsubsets_call = bquote(regsubsets(.(formula), data = .(substitute(data)), nvmax = 2))