R中矩阵的行方差

Tob*_*oby 13 r

我想计算矩阵中每行的方差.对于以下矩阵A

     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    5    6   10
[3,]   50    7   11
[4,]    4    8   12
Run Code Online (Sandbox Code Playgroud)

我想得到

[1]  16.0000   7.0000 564.3333  16.0000
Run Code Online (Sandbox Code Playgroud)

我知道我可以实现这一目标apply(A,1,var),但是有更快或更好的方法吗?从八度,我可以这样做var(A,0,2),但我不知道如何使用R Y中的var()函数的参数.

编辑:典型块的实际数据集大约有100行和500列.但总数据量约为50GB.

Dav*_*urg 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
Run Code Online (Sandbox Code Playgroud)

使用@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
Run Code Online (Sandbox Code Playgroud)

您还可以创建一个更通用的函数,它将接收类似于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 
Run Code Online (Sandbox Code Playgroud)

  • 是的,加快了一点(很多).我生命的最后298毫秒去了哪里? (3认同)
  • @skan在矩阵中如此子集,例如,`RowVar(A [,1:3)`将仅在前3列上运行它.另外,看一下`matrixStats`包,它们几乎涵盖了那里的所有内容.你也可以直接从GH下载这些功能,见[这里](https://gist.github.com/DavidArenburg/cca995ec1709c0d4735d) (2认同)

Ric*_*ven 13

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 
Run Code Online (Sandbox Code Playgroud)

进行10,000次计算需要300毫秒太长时间吗?