1

考虑这个片段:

> a <- 1:1e7
> b <- 1:1e7
> (sizes <- sapply(c("a","b"),function(n) {
    s <- object.size(get(n))
    cat(n,": ")
    print(s,units="auto")
  }))
a : 38.1 Mb
b : 38.1 Mb
       a        b 
40000040 40000040
> class(sizes)
[1] "numeric"
> (s <- sum(sizes))
[1] 80000080
> class(s) <- "object_size"
> s
80000080 bytes
> print(s,units="auto")
76.3 Mb

请注意

  1. sapply"object_size"sizes(lapply不删除类,但其结果 - a list- 不能传递给sum)。

  2. "object_size"打印对象units="B"而不是"auto"

两者似乎都不是最理想的;的值sizes应打印为

      a       b
38.1 Mb 38.1 Mb 

我的问题是:这只是一个错误,还是这种行为背后有一些深层原因?

4

2 回答 2

2

如果要将列表的元素加在一起,请考虑使用该Reduce函数。它会将二元运算符(+在这种情况下)应用于向量或列表。+运算符不会剥离类和其他属性sapply,例如sum

> a <- 1:1e7
> b <- 1:1e7
> (sizes <- lapply(c("a","b"),function(n) {
+ s <- object.size(get(n))
+     cat(n,": ")
+     print(s,units="auto")
+   }))
a : 38.1 Mb
b : 38.1 Mb
[[1]]
40000040 bytes

[[2]]
40000040 bytes

> 
> Reduce('+', sizes)
80000080 bytes
> print(.Last.value, units='auto')
76.3 Mb
于 2013-06-25T15:51:26.093 回答
2

我不认为这里有任何错误。

事情的真相是,R 对象的类只是一个属性,就像任何其他对象一样,当sapply将结果简化为向量时,所有属性都被剥离了。您可以通过这样做来解决问题,尽管输出非常难看

> class(sizes) <- "object_size"
> sizes
40000040 bytes40000040 bytes
> sum(sizes)
80000080 bytes

正如您所指出lapply的,保留了类(因为它没有简化),如果您想计算结果的总和,您可以调用以下命令。

> (sizes <- lapply(c("a","b"),function(n) {
    s <- object.size(get(n))
    cat(n,": ")
    print(s,units="auto")
  }))
a : 38.1 Mb
b : 38.1 Mb
[[1]]
40000040 bytes

[[2]]
40000040 bytes

> (s <- do.call(sum, sizes))
80000080

sum也剥离了类,因为没有定义命名"sum.object_size"的函数,而是.Primitive("sum")使用它,这再次将其简化为数字。您可以重载它,但@Greg Snow 的答案 usingReduce更优雅。

> `sum.object_size` <- function(...){
    s <- sum(unlist(list(...)))
    class(s) <- "object_size"
    s
}
> do.call(sum, sizes)
80000080 bytes

的默认行为print.object_size是使用units="b",无论您在sapply调用中设置什么。如果您想在默认情况下以不同方式打印它们,则必须重载print.object_size

> print.object_size <- function(..., units="auto")
    getFromNamespace("print.object_size", "utils")(..., units=units)
> sizes
[[1]]
38.1 Mb

[[2]]
38.1 Mb

编辑:关于“承诺已在评估中”错误的注释

考虑以下函数:

f <- function(x=1){
    h <- function(x) x
    h(x=x)
}
g <- function(x=1){
    h <- function(x=x) x
    h()
}

f将毫无问题地运行,因为xh(x=x)的环境中搜索 in fg另一方面将导致错误,因为xh()的环境中搜索 in h,但未定义它。

于 2013-06-25T15:30:09.787 回答