使用transformBy()(部分doBy包)的R(统计)范围错误

时间:2010-09-18 16:16:25

标签: r statistics

我认为在使用transformBy()时,我遇到了一个范围错误,这是R的doBy包的一部分。这是一个简单的问题示例:

> library(doBy)
>
> test.data = data.frame(
+  herp = c(1,2,3,4,5),
+  derp = c(2,3,1,3,5)
+ )
>
> transformData = function(data){
+ 
+  five = 5
+ 
+  transformBy(
+   ~ herp,
+   data=data,
+   sum=herp + derp + five
+  )
+ }
>
> transformData(test.data)
Error in eval(expr, envir, enclos) : object 'five' not found

当我在子范围(非全局范围)中运行transformBy()时,似乎没有局部变量或函数可用于transformBy。另一方面,如果我在全局定义这些变量或函数,它们就变得可用了。这是一个有点修改的例子:

> library(doBy)
>
> test.data = data.frame(
+  herp = c(1,2,3,4,5),
+  derp = c(2,3,1,3,5)
+ )
>
> five = 5
>
> transformData = function(data){
+  transformBy(
+   ~ herp,
+   data=data,
+   sum=herp + derp + five
+  )
+ }
>
> transformData(test.data)
  herp derp sum
1    1    2   8
2    2    3  10
3    3    1   9
4    4    3  12
5    5    5  15

我是否误解了有关transformBy应该如何工作或有什么破坏的事情?

版本:

  • ubuntu:8.04(x64)
  • R:2.10.1
  • doBy:4.0.5

3 个答案:

答案 0 :(得分:2)

这是一个以各种方式提出的问题。 显然,R中的范围有些奇怪。

编辑:这不是R中的范围与我天真的预期不同,而是与transformBy()的范围不同。请参阅Erik的答案。

我通过在全局环境中分配临时环境来解决这个问题,例如:

transformData = function(data){

  temp_env <<- new.env(hash=T) #hashed environment for easy access
  temp_env$five = 5

  out <- transformBy(
   ~ herp,
   data=data,
   sum=herp + derp + temp_env$five
  )
  rm(temp_env,envir=.GlobalEnv) # cleanup 
  return(out)
 }

答案 1 :(得分:2)

我认为这是transformBy函数中的一个错误。如果查看transformBy的源代码,它会创建一个名为transform2的子函数,它在数据框的上下文中首先计算最后一个参数,其中parent.frame()作为封闭环境。然后,它会在lapply上调用transform2

由于R使用词法作用域语义(参​​见http://cran.r-project.org/doc/manuals/R-intro.html#Scope),因此有效作用域层次结构为data,然后lapply为全局。我认为正确的解决方法是在pf <- parent.frame()定义之外添加transform2形式的声明,然后在pf声明中引用eval

答案 2 :(得分:2)

这在?transformBy帮助页面中有明确记载,因此 一个错误。

详细说明:

 The ... arguments are tagged vector expressions, which are
 evaluated in the data frame data. The tags are matched against
 names(data), and for those that match, the value replace the
 corresponding variable in data, and the others are appended to
 data.

只需将对象“五”作为data.frame“data”的一部分,然后 它会像你期望的那样工作。目前该功能正在尝试 评估“数据”data.frame中的“五”,当然这是失败的。