我想计算矩阵中每行的方差。对于以下矩阵A
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 5 6 10
[3,] 50 7 11
[4,] 4 8 12
我想得到
[1] 16.0000 7.0000 564.3333 16.0000
我知道我可以用apply(A,1,var)
实现这一目标,但有更快或更好的方法吗?从八度音阶开始,我可以使用var(A,0,2)
执行此操作,但我不知道如何使用R中Y
函数的var()
参数。
编辑:典型块的实际数据集大约有100行和500列。但总数据大约为50GB。
答案 0 :(得分:26)
您可以使用var
和rowSums
rowMeans
进行矢量化
RowVar <- function(x, ...) {
rowSums((x - rowMeans(x, ...))^2, ...)/(dim(x)[2] - 1)
}
RowVar(A)
#[1] 16.0000 7.0000 564.3333 16.0000
使用@Richards数据,产量
microbenchmark(apply(m, 1, var), RowVar(m))
## Unit: milliseconds
## expr min lq median uq max neval
## apply(m, 1, var) 343.369091 400.924652 424.991017 478.097573 746.483601 100
## RowVar(m) 1.766668 1.916543 2.010471 2.412872 4.834471 100
您还可以创建一个更通用的函数,它将接收类似于apply
的语法,但仍将保持矢量化(由于矩阵需要先转置,因此列方式方差会更慢)
MatVar <- function(x, dim = 1, ...) {
if(dim == 1){
rowSums((x - rowMeans(x, ...))^2, ...)/(dim(x)[2] - 1)
} else if (dim == 2) {
rowSums((t(x) - colMeans(x, ...))^2, ...)/(dim(x)[1] - 1)
} else stop("Please enter valid dimension")
}
MatVar(A, 1)
## [1] 16.0000 7.0000 564.3333 16.0000
MatVar(A, 2)
V1 V2 V3
## 547.333333 1.666667 1.666667
答案 1 :(得分:12)
这是apply()
有用的主要原因之一。它意味着在数组或矩阵的边缘上运行。
set.seed(100)
m <- matrix(sample(1e5L), 1e4L)
library(microbenchmark)
microbenchmark(apply(m, 1, var))
# Unit: milliseconds
# expr min lq median uq max neval
# apply(m, 1, var) 270.3746 283.9009 292.2933 298.1297 343.9531 100
300毫秒太长,无法进行10,000次计算?