Fra*_*ank 43 r matrix diagonal
我正在查看这个答案中的基准,并希望将它们与diag
(用于不同的答案)进行比较.不幸的是,似乎diag
需要很长时间:
nc <- 1e4
set.seed(1)
m <- matrix(sample(letters,nc^2,replace=TRUE), ncol = nc)
microbenchmark(
diag = diag(m),
cond = m[row(m)==col(m)],
vec = m[(1:nc-1L)*nc+1:nc],
mat = m[cbind(1:nc,1:nc)],
times=10)
Run Code Online (Sandbox Code Playgroud)
评论:我测试了这些identical
.我从这个家庭作业问题的答案中选了一个"cond" .结果类似于整数矩阵,1:26
而不是letters
.
结果:
Unit: microseconds
expr min lq mean median uq max neval
diag 604343.469 629819.260 710371.3320 706842.3890 793144.019 837115.504 10
cond 3862039.512 3985784.025 4175724.0390 4186317.5260 4312493.742 4617117.706 10
vec 317.088 329.017 432.9099 350.1005 629.460 651.376 10
mat 272.147 292.953 441.7045 345.9400 637.506 706.860 10
Run Code Online (Sandbox Code Playgroud)
它只是一个矩阵子集操作,所以我不知道为什么会有这么多开销.查看函数内部,我看到几个检查,然后c(m)[v]
,v
"vec"基准中使用的向量相同.定时这两个......
v <- (1:nc-1L)*nc+1:nc
microbenchmark(diaglike=c(m)[v],vec=m[v])
# Unit: microseconds
# expr min lq mean median uq max neval
# diaglike 579224.436 664853.7450 720372.8105 712649.706 767281.5070 931976.707 100
# vec 334.843 339.8365 568.7808 646.799 663.5825 1445.067 100
Run Code Online (Sandbox Code Playgroud)
......似乎我找到了我的罪魁祸首.所以,对我的问题的新变化是:为什么会出现一个看似不必要的,非常耗时c
的diag
?
Ste*_*rin 14
摘要
截至R版3.2.1(世界着名宇航员)diag()
已收到更新.讨论转移到r-devel,注意到它c()
剥离了非名称属性,可能就是它放在那里的原因.虽然有些人担心移除c()
会对类似矩阵的物体造成未知问题,但是Peter Dalgaard发现," c()
内部diag()
有效的唯一情况是M[i,j] != M[(i-1)*m+j]
AND c(M)
将按M
列主要顺序串联,这样M[i,j] == c(M)[(i-1)*m+j]
."
Luke Tierney对@Frank的删除进行了测试c()
,发现它对CRAN或BIOC没有任何影响,因此实现了在第27行用x [...]替换c(x)[...] .这导致相对较大的加速diag()
.下面是速度测试,显示了R 3.2.1版本的改进diag()
.
library(microbenchmark)
nc <- 1e4
set.seed(1)
m <- matrix(sample(letters,nc^2,replace=TRUE), ncol = nc)
microbenchmark(diagOld(m),diag(m))
Unit: microseconds
expr min lq mean median uq max neval
diagOld(m) 451189.242 526622.2775 545116.5668 531905.5635 540008.704 682223.733 100
diag(m) 222.563 646.8675 644.7444 714.4575 740.701 1015.459 100
Run Code Online (Sandbox Code Playgroud)