Re: [问题] 两个矩阵同时操作

楼主: celestialgod (天)   2017-07-13 21:36:54
这种事情杀鸡焉用牛刀,用循环最快也最简单
A <- matrix(c(1:48),ncol = 16L)
B <- matrix(c(1:80),ncol = 16L)
mutual <- function(delta, a, FUN = "*"){
delta <- as.matrix(delta)
a <- as.matrix(a)
result <- matrix(outer(delta, a, FUN), nrow = nrow(delta))
return(result)
}
f <- function(a,b){
return(as.matrix(a) %*% t(b))
}
g <- function(A, B){
out <- array(dim = c(nrow(A), nrow(B), ncol(A)))
for (i in 1L:ncol(A)) out[ , , i] <- A[ , i] %o% B[ , i]
return(out)
}
library(microbenchmark)
microbenchmark(
original = lapply(1L:ncol(A) , function(x) mutual(A[,x], B[,x])),
simplify2array = simplify2array(lapply(1:ncol(A) , function(x) f(A[,x],
B[,x]))),
forLoop = g(A, B), times = 20L
)
# Unit: microseconds
# expr min lq mean median uq max neval
# original 419.838 423.6410 702.6495 426.2735 431.6865 5669.115 20
# simplify2array 222.938 224.8400 389.2933 229.0820 236.2500 3406.385 20
# forLoop 183.734 187.5375 486.0899 190.7555 195.4375 5987.723 20
不过我的R是3.4.0,所以JIT加持快很多,不确定其他版本是不是一样水准
A <- matrix(c(1:48000), ncol = 1600L)
B <- matrix(c(1:8000), ncol = 1600L)
microbenchmark(
original = lapply(1L:ncol(A) , function(x) mutual(A[,x], B[,x])),
simplify2array = simplify2array(lapply(1:ncol(A) , function(x) f(A[,x],
B[,x]))),
forLoop = g(A, B), times = 20L
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# original 44.37369 46.77744 48.24738 47.98765 49.32776 53.08230 20
# simplify2array 21.89062 23.83928 28.64161 25.65306 26.21406 94.59203 20
# forLoop 21.23322 22.69387 24.72092 24.64764 25.65935 31.67589 20
※ 引述《wheado (principal component QQ)》之铭言:
: [问题类型]:
: 两个满大的矩阵同时透过row来进行操作
: 用一个例子来说明我的问题
: [软件熟悉度]:
: 新手
: [问题叙述]:
: A=[ 1 2 3 4 ] B=[ 1 2 3 4 ] A与B的column相同
: [ 5 6 7 8 ] [ 5 6 7 8 ]
: [ 9 10 11 12 ] [ 9 10 11 12 ]
: [ 13 14 15 16 ] [ 13 14 15 16 ]
: [ 17 18 19 20 ] [ 17 18 19 20 ]
: [ 21 22 23 24 ]
: [ 25 26 27 28 ]
: [ 29 30 31 32 ]
: 我想透过类似apply的运算,将A与B两个矩阵的Column分别提出来运算,
: 运算内容是有点复杂,用上述例子来说明。
: A* B*
: 以第一个column来说,提出来的分别是 [ 1 ] [ 1 ]
: [ 5 ] [ 5 ]
: [ 9 ] [ 9 ]
: [ 13 ] [ 13 ]
: [ 17 ] [ 17 ]
: [ 21 ]
: [ 25 ]
: [ 29 ]
: 接着将A*每个元素与B*每个元素"乘积",也就是产生一个矩阵(向量也可以)如下
: [ 1*1 1*5 1*9 1*13 1*17 1*21 1*25 1*29 ]
: [ 5*1 5*5 5*9 5*13 5*17 5*21 5*25 5*29 ]
: [ 9*1 9*5 9*9 9*13 9*17 9*21 9*25 9*29 ]
: [ 13*1 13*5 13*9 13*13 13*17 13*21 13*25 13*29 ]
: [ 17*1 17*5 17*9 17*13 17*17 17*21 17*25 17*29 ]
: 以此类推会产生 4 个矩阵(或向量),输出方式目前想到只有 list 比较方便。
: 由于我们两个矩阵A与B可能会有点大,因此希望可以稍微快一些的计算方法,
: 又希望程式码可读性可以高一点,让自己以后比较容易看懂(修改)。
: ~~~谢谢各位神人阅读~~~
: [程式范例]:
: 我有尝试了一个方式,但我觉得可读性很低,
: 希望可以改的更简单易懂,速度更快一些。
: 我是用 指令outer 来做,以下程式码,矩阵大一点就要等一些时间了QQ
: 程式码贴于以下网址:
: http://ideone.com/NmFGVT
: [环境叙述]:
: win10 + R_64
: [关键字]:
: outer apply mapply lapply
作者: wheado (principal component QQ)   2017-07-13 21:49:00
谢谢大师不厌其烦指教,直觉上就是想避开loop,没想到loop威力还真是简单强大。
作者: f496328mm (为什么会流泪)   2017-07-13 21:53:00
R 3.4 有加强循环的威力
作者: Edster (Edster)   2017-07-13 22:02:00
for循环变快真是好消息.
作者: sacidoO (阿骂)   2017-07-15 22:35:00
推C神

Links booklink

Contact Us: admin [ a t ] ucptt.com