7

我对 colMeans 函数有疑问。是否有这样的版本在遇到长度为 1 的列时不会返回错误?例如

temp<-cbind(c(2,2),c(3,4))
colMeans(temp)

[1] 2.0 3.5

但是对于这个

temp2<-c(2,2)
colMeans(temp2)

Error in colMeans(temp2) : 
'x' must be an array of at least two dimensions

但是,如果我将函数均值应用于每一列,它会正确得出 2 和 2 的值。

我写了一个函数来做到这一点

testfun<-function(i,x){
mean(x[,i])
}
sapply(1:ncol(x),testfun,x)

给出与 colMeans 相同的结果。
我听说 colMeans 应该比这种方法快得多。那么,当我的列大小为 1 时,是否有一个 colMeans 版本可以使用。

4

3 回答 3

8

正如@Paul 指出的那样,它的参数(来自)colMeans期望“一个二维或更多维的数组” 。但不是数组x?colMeanstemp2

is.array(temp2)
# [1] FALSE

temp2可以做成数组:

(tempArray <- array(temp2, dim = c(1, 2)))
#      [,1] [,2]
# [1,]    2    2

colMeans(tempArray)
# [1] 2 2

也许temp2来自对数组进行子集化,例如

array(temp2, dim = c(2, 2))[1, ]

但这不是一个数组。要将其保留为数组,drop = FALSE请在括号内添加:

array(temp2, dim = c(2, 2))[1, , drop = FALSE]
#      [,1] [,2]
# [1,]    2    2

然后您可以在子集数组上使用 colMeans。

于 2012-05-16T10:06:27.833 回答
4

colMeans函数适用于 n 维数组。当您的列大小为 1(1 列或 1 行??)时,您实际上有一个向量。在向量上,使用 justmean就可以了。在速度方面,计算一百万个数字的平均值非常快:

> system.time(mean(runif(10e5)))
   user  system elapsed 
  0.038   0.000   0.038 
于 2012-05-16T09:06:31.257 回答
2

@PaulHiemstra 和 @BenBarnes 提供了正确的答案。我只是想补充他们的解释。

向量与数组

向量是 R 中的基本数据结构。几乎所有内容在内部都表示为向量,甚至是列表(除了一种特殊的列表,点对列表,请参阅 参考资料?list)。数组只是带有附加属性的向量,该dim属性描述了对象的尺寸。考虑以下:

v <- c(1:10)
a <- array(v, dim = c(5, 2))
length(v) # 10
length(a) # 10
attributes(v) # NULL
attributes(a) # $dim 10  1
is.vector(v) # TRUE
is.array(v) # FALSE
is.vector(a) # FALSE
is.array(a) # TRUE

两者都是v长度。唯一的区别是附加了属性。由于这个附加属性,R在外部将其视为数组而不是向量。仅修改属性可以将 R 的对象的外部表示从数组更改为向量并返回:a10adimadim

attr(a, "dim") <- NULL
is.vector(a) # TRUE
is.array(a) # FALSE
attr(v, "dim") <- c(5, 2)
is.vector(v) # FALSE
is.array(v) # TRUE

在您的示例中,temp2是一个矢量对象,因此缺少dim属性。colMeans期望具有至少长度为 2(二维)array的属性的对象。dim您可以轻松地转换temp2为具有单列的二维数组:

temp3 <- array(temp2, dim = c(length(temp2), 1)) 
# or:
temp4 <- temp2
attr(temp4, "dim") <- c(length(temp2), 1)
is.array(temp2) # FALSE
is.array(temp3) # TRUE
is.array(temp4) # TRUE

colMeans() 与 mean()

@PaulHiemstra 是对的,与其将向量转换为单列 for colMeans(),不如仅在向量上使用更为常见mean()。但是,您是对的,colMeans()速度更快。我相信这是因为它对格式正确的数据的检查少了一点,但我们必须查看内部 C 代码才能确定。考虑这个例子:

# Create vector "v" and array "a"
n <- 10e7
set.seed(123) # Set random number seed to ensure "v" and "a[,1]" are equal
v <- runif(n)
set.seed(123) # Set random number seed to ensure "v" and "a[,1]" are equal
a <- array(runif(n), dim=c(n, 1))

# Test that "v" and "a[,1]" are equal
all.equal(v, a[,1]) # TRUE

# Functions to compare
f1 <- function(x = v){mean(x)} # Using mean on vector
f2 <- function(x = a){mean(x)} # Using mean on array
f3 <- function(x = a){colMeans(x)} # Using colMeans on array

# Compare elapsed time
system.time(f1()) # elapsed time = 0.344
system.time(f2()) # elapsed time = 0.366
system.time(f3()) # elapsed time = 0.166

colMeans()在数组上比mean()在向量或数组上更快。但是,大多数情况下,这种加速可以忽略不计。我发现只mean()在向量或单列数组上使用更自然。colMeans()但是,如果你是一个真正的速度恶魔,你可能会在晚上睡得更好,因为你知道通过使用单列数组可以节省数百毫秒的处理时间。

于 2012-05-16T14:13:38.390 回答