colMeans在R中运行并遇到大小为1的列的问题

时间:2012-05-16 09:03:00

标签: r

我对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

但是,如果我将函数mean应用于每一列,它会正确地得到值2和2.

我写了一个函数来做这个

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

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

3 个答案:

答案 0 :(得分:8)

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

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。

答案 1 :(得分:4)

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

> system.time(mean(runif(10e5)))
   user  system elapsed 
  0.038   0.000   0.038 

答案 2 :(得分: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

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

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期望array对象的dim属性至少为长度为2(二维)。您可以使用单个列轻松地将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是对的,而不是将向量转换为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()来节省几百毫秒的处理时间。