1

我发现 zoo's在函数体中使用时transform无法使用其他(即不是 zoo 对象的一部分)变量。

让我解释:

我在提示符下输入了以下代码来创建一个小的两列动物园对象z并添加一个从现有列和一个变量计算的新列x

library(zoo)
z <- zoo(matrix(1:10, ncol=2, dimnames=list(NULL, c("a", "b"))), order.by=2001:2005)
x <- 2
transform(z, c = x*a)

我得到了想要的结果,一个带有新列的 zoo 对象c。这里没问题。

现在我想transform在函数体中使用;计算的变量作为参数传递给函数:

rm(x)
f <- function(data, x) { transform(data, c = x*a) }
f(z, 2)

这与Error in eval(expr, envir, enclos) (from #1) : object 'x' not found. x <- 2如果我在提示符下分配,它可以工作(因此rm(x)如上所述)。

使用数据帧(即transform.data.frame)没有问题。

我认为当transform.zoo调用时transform.data.frame,形式的绑定f会丢失。我不太了解 R 的环境,无法找出这里到底出了什么问题。

编辑补充:不仅transform不能得到形式,而且不能从函数体内得到变量。

有没有办法让transform看到x?(我知道我可以在没有转换的情况下工作,但它是用于简短代码的好工具。)

4

1 回答 1

2

我认为最好的建议是:不要那样做!

transform(), with(),subset()确实是顶层使用的糖,使编写数据操作代码更容易一些。如果您正在编写函数,则应使用通用替换函数[<-[[<-具体取决于您在做什么。

如果您不相信我,请参阅中的警告?transform

Warning:

    This is a convenience function intended for use interactively.
    For programming it is better to use the standard subsetting
    arithmetic functions, and in particular the non-standard
    evaluation of argument ‘transform’ can have unanticipated
    consequences.

我所说的使用[<-or[或其他功能的意思是这样f

f <- function(obj, x) {
  cd <- coredata(obj)
  cd <- cbind(cd, c = x * cd[, "a"])
  zoo(cd, index(obj), attr(obj, "frequency"))
}

f(z, 2)

这给出了预期的结果

> transform(z, c = x*a)
     a  b  c
2001 1  6  2
2002 2  7  4
2003 3  8  6
2004 4  9  8
2005 5 10 10
> f(z, 2)
     a  b  c
2001 1  6  2
2002 2  7  4
2003 3  8  6
2004 4  9  8
2005 5 10 10

f很复杂,因为coredata(obj)它是一个矩阵。可能会更整洁

f2 <- function(obj, x) {
    cd <- as.data.frame(coredata(obj))
    cd[, "c"] <- x * cd[, "a"] ## or cd$c <- x * cd$a
    zoo(cd, index(obj), attr(obj, "frequency"))
}

f2(z, 2)

> f2(z, 2)
     a  b  c
2001 1  6  2
2002 2  7  4
2003 3  8  6
2004 4  9  8
2005 5 10 10

您确实需要了解要使用的环境和评估框架transform()-您不需要学习使用eval(),这是内部调用的内容,并为(评估的环境)和外壳transform()指定正确的值. 见。envirenclos?eval

于 2013-06-27T15:55:36.150 回答