R 按列列出的滚动和乘积

R 按列列出的滚动和乘积,r,matrix,rcpp,R,Matrix,Rcpp,我有两个矩阵,我想把它们相乘,这样得到的矩阵的每个值都是前两个矩阵中相同列的滚动和积 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,]

我有两个矩阵,我想把它们相乘,这样得到的矩阵的每个值都是前两个矩阵中相同列的滚动和积

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
在示例中,
10.7
值以上的输出计算如下:

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

有人知道怎么做吗?我一直在玩
RcppRoll
软件包,但没有得到正确的答案。解决方案越快越好,因为这是需要多次迭代的优化的一部分。

您正在寻找。在R中,函数
convolve
通过FFT(快速傅立叶变换)计算两个向量的卷积。读取
?卷积
。注意,我们特别需要
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

x您正在寻找。在R中,函数
convolve
通过FFT(快速傅立叶变换)计算两个向量的卷积。读取
?卷积
。注意,我们特别需要
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
x使用colSums:

t(
  sapply(1:(nrow(x) - nrow(y) + 1), function(i){
    colSums(x[i:((nrow(y)) + i - 1), ] * y)
    })
  )
基于更大的示例数据(在ZheyuanLi的回答中提供),microbenchmark:

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
使用colSums:

t(
  sapply(1:(nrow(x) - nrow(y) + 1), function(i){
    colSums(x[i:((nrow(y)) + i - 1), ] * y)
    })
  )
基于更大的示例数据(在ZheyuanLi的回答中提供),microbenchmark:

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

这可以通过像这样的一行中的
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)

这可以通过像这样的一行中的
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)

谢谢,这给了我想要的答案。我不确定什么是卷积,但我会用你提供的链接来阅读。我唯一的保留是您使用的是sapply(),每次优化我都要花很多时间。不会慢下来吗?也可以考虑这个变化:<代码> MpIp(卷积),as .DATA。框架(X),AS。数据。框架(Y),MyErgs=列表(类型=“过滤器”)< /代码>谢谢,这给了我我正在寻找的答案。我不确定什么是卷积,但我会用你提供的链接来阅读。我唯一的保留是您使用的是sapply(),每次优化我都要花很多时间。不会慢下来吗?也可以考虑这个变化:<代码> MpIOP(卷积,as .Dista.框架(x),as .Dista.框架(y),MyErgs=列表(type =“filter”))< /代码>,在我思考一些你们已经发现的有代表性的数据的时候。所以,说得很清楚,@zx8754提供了一个更快的例子。在我想出一些有代表性的数据的时候,你们已经弄明白了。因此,@zx8754提供了更快的示例。