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提供了更快的示例。