2016-09-27 17 views
1

我有兩個矩陣,我想將它們放在一起,使得得到的矩陣的每個值都是前兩個矩陣中相同列的滾動和積。滾動積和列

x<-matrix(seq(1:30), ncol=3) 
x 
     [,1] [,2] [,3] 
[1,] 1 11 21 
[2,] 2 12 22 
[3,] 3 13 23 
[4,] 4 14 24 
[5,] 5 15 25 
[6,] 6 16 26 
[7,] 7 17 27 
[8,] 8 18 28 
[9,] 9 19 29 
[10,] 10 20 30 
y<-matrix(rep(seq(1:3), 4), ncol=3)/10 
y 
    [,1] [,2] [,3] 
[1,] 0.1 0.2 0.3 
[2,] 0.2 0.3 0.1 
[3,] 0.3 0.1 0.2 
[4,] 0.1 0.2 0.3 

所以結果看起來像:

output[2, 2] = 12 * 0.2 + 13 * 0.3 + 14 * 0.1 + 15 * 0.2 

是否有人知道如何做到這一點:

1.8 9.9  20.3 
2.5 10.7 21.2 
3.2 11.5 22.1 
3.9 12.3 23 
4.6 13.1 23.9 
5.3 13.9 24.8 
6 14.7 25.7 

在示例輸出上面的10.7值作爲計算?我一直在玩RcppRoll包,但無法得到正確的答案。解決方案越快越好,因爲這是需要進行多次迭代的優化的一部分。

回答

5

使用colSums:

t(
    sapply(1:(nrow(x) - nrow(y) + 1), function(i){ 
    colSums(x[i:((nrow(y)) + i - 1), ] * y) 
    }) 
) 

基於更大的示例數據(在ZheyuanLi的答案提供),微基準測試:

Unit: milliseconds 
expr  min  lq  mean median  uq  max neval cld 
    zx 179.8928 186.8033 202.5204 192.3973 199.7500 299.5910 100 a 
    ZL 365.9814 368.3878 391.8303 370.0935 373.4502 489.5045 100 b 
+0

在我花時間想想你們已經知道的一些有代表性的數據。所以,要清楚的是,@ zx8754提供了更快的示例。 – user3390169

4

您在尋找convolution。在R中,函數convolve通過FFT(快速傅里葉變換)計算兩個向量的卷積。閱讀?convolve。請注意,我們特別需要type = "filter"

例如,對於x[,1]y[,1]卷積是:

convolve(x[,1], y[,1], type = "filter") 
# [1] 1.8 2.5 3.2 3.9 4.6 5.3 6.0 

這是簡單的換東西了一個sapply

sapply(seq_len(ncol(x)), function (i) convolve(x[,i], y[,i], type = "filter")) 

#  [,1] [,2] [,3] 
#[1,] 1.8 9.9 20.3 
#[2,] 2.5 10.7 21.2 
#[3,] 3.2 11.5 22.1 
#[4,] 3.9 12.3 23.0 
#[5,] 4.6 13.1 23.9 
#[6,] 5.3 13.9 24.8 
#[7,] 6.0 14.7 25.7 

我想在你的背景,你的矩陣x是一個很薄的矩陣,即它的行數多於列數。我的sapply在列上。爲什麼不進行實際測試並做一些分析?

x <- matrix(rnorm(3000 * 100), 3000) ## `3000 * 100` matrix 
y <- matrix(rnorm(100 * 100), 100) ## `100 * 100` matrix 

Rprof("foo.out") 
sapply(seq_len(ncol(x)), function (i) convolve(x[,i], y[,i], type = "filter")) 
Rprof(NULL) 

summaryRprof("foo.out")$by.total 

       total.time total.pct self.time self.pct 
"sapply"    1.32 100.00  0.00  0.00 
"FUN"     1.30  98.48  0.02  1.52 
"lapply"    1.30  98.48  0.00  0.00 
"convolve"    1.28  96.97  0.08  6.06 
"fft"     1.12  84.85  1.12 84.85 
"rep.int"    0.04  3.03  0.04  3.03 
"array"    0.02  1.52  0.02  1.52 
"c"     0.02  1.52  0.02  1.52 
"Re"     0.02  1.52  0.02  1.52 
"simplify2array"  0.02  1.52  0.00  0.00 

的時間96%+花在convolve,因而sapply開銷是可以忽略的。

+0

謝謝你,這給我的答覆我尋找。我不確定卷積究竟是什麼,但我會使用您提供的鏈接閱讀它。我唯一的保留是你使用sapply(),我必須爲每次優化做很多時間。這不會減慢速度嗎? – user3390169

+0

也可以考慮這個變化:'mapply(convolve,as.data.frame(x),as.data.frame(y),MoreArgs = list(type =「filter」))' –

4

這可以通過rollapply在這樣一個行來完成。它使用整個對象方法,即沒有明確的下標。

library(zoo) 
rollapply(x, nrow(y), function(x) colSums(x*y), by.column = FALSE) 

,並提供:

 [,1] [,2] [,3] 
[1,] 1.8 9.9 20.3 
[2,] 2.5 10.7 21.2 
[3,] 3.2 11.5 22.1 
[4,] 3.9 12.3 23.0 
[5,] 4.6 13.1 23.9 
[6,] 5.3 13.9 24.8 
[7,] 6.0 14.7 25.7 

注:雖然沒有任何短,使用magrittr這可能交替寫成:

library(magrittr) 
library(zoo) 
x %>% rollapply(nrow(y), . %>% `*`(y) %>% colSums, by.column = FALSE)