我有一个像这样的矩阵列表:
[[1]]
[,1] [,2] [,3]
[1,] 0.8 2.0 3.2
[2,] 2.0 3.2 4.4
[3,] 3.2 4.4 5.6
[[2]]
[,1] [,2] [,3]
[1,] -1.95 1.00 3.95
[2,] 1.00 3.95 6.90
[3,] 3.95 6.90 9.85
[[3]]
[,1] [,2] [,3]
[1,] -1.1 0.1 1.3
[2,] 0.1 1.3 2.5
[3,] 1.3 2.5 3.7
我想得到一个向量,列表中每个矩阵只有一个特定的行和列,行由矢量选择。
我做了一个代码来执行此操作:
xmin <- NULL
row <- c(2,3,2)
for(i in 1:3){
xmin[i] <- lista[[i]][row[i] , 1]
}
问题在于我想以最有效的方式进行此选择,我希望避免for
循环,如果可能的话,我希望避免mapply
和lapply
这样的函数,因为我必须数百万次调用此功能。计时器mapply
略微低于for
循环计时,但它的速度不够快。
是否有任何可能的方法使用R基础选择函数([[
,[
或$
运算符)进行此子集化?
答案 0 :(得分:2)
如果您的矩阵都具有相同的尺寸,您可以将它们转换为三维数组并使用索引。
lst <- list(matrix(1:9, 3, 3), matrix(10:18, 3, 3), matrix(19:27, 3, 3))
arr <- do.call(cbind, lst)
dim(arr) <- c(3, 3, 3)
getl <- function(row, col)
sapply(1:3, function(i) lst[[i]][row[i], col])
geta <- function(row, col)
arr[cbind(row, col, 1:3)]
> system.time(replicate(100000, getl(1, 2)))
user system elapsed
2.65 0.00 2.65
> system.time(replicate(100000, geta(1, 2)))
user system elapsed
0.47 0.00 0.47
答案 1 :(得分:2)
我觉得值得对一些替代方案进行基准测试,包括akrun和Hong Ooi's。
1)A&#34; for&#34;具有预先分配结果的循环:
ff1 = function(x, vec)
{
ans = numeric(length(x))
for(i in seq_along(x)) ans[i] = x[[i]][vec[i], 1]
return(ans)
}
2)编译&#34; for&#34;循环:
cmpff1 = compiler::cmpfun(ff1)
3)A mapply
:
ff2 = function(x, vec) mapply(function(elt, i) elt[i, 1], x, vec)
4)cbind
使用矩阵索引(Hong Ooi):
ffHO = function(x, vec)
"dim<-"(do.call(cbind, x),
c(dim(x[[1]]), length(x)))[cbind(vec, 1, seq_len(length(x)))]
5)修改(4),只添加一个属性:
ffHO2 = function(x, vec)
"dim<-"(unlist(x),
c(dim(x[[1]]), length(x)))[cbind(vec, 1, seq_len(length(x)))]
比较:
myls = replicate(5e4, matrix(runif(100), 10, 10), simplify = FALSE)
vec = sample(1:10, 5e4, T)
ans1 = ff1(myls, vec)
ans2 = cmpff1(myls, vec)
ans3 = ff2(myls, vec)
ans4 = ffHO(myls, vec)
ans5 = ffHO2(myls, vec)
identical(ans1, ans2)
#[1] TRUE
identical(ans1, ans3)
#[1] TRUE
identical(ans1, ans4)
#[1] TRUE
identical(ans1, ans5)
#[1] TRUE
microbenchmark::microbenchmark(ff1(myls, vec), cmpff1(myls, vec),
ff2(myls, vec), ffHO(myls, vec),
ffHO2(myls, vec), times = 15)
#Unit: milliseconds
# expr min lq median uq max neval
# ff1(myls, vec) 113.26685 132.36089 138.28047 147.97974 240.7101 15
# cmpff1(myls, vec) 51.23446 55.35398 58.18066 69.07220 82.4652 15
# ff2(myls, vec) 119.44709 138.54739 145.66654 156.75227 219.9084 15
# ffHO(myls, vec) 119.57063 130.52029 141.02867 149.21742 174.8242 15
# ffHO2(myls, vec) 40.69163 41.31125 47.80939 48.55551 118.1069 15