如何在 Rcpp 中对矩阵的 10 步行求和?
How to sum 10 step rows of matrix in Rcpp?
我想使用 Rcpp 获得以下结果。
当大数据时,R 很慢。
因此,我尝试在 Rcpp 中编码。
x <- matrix(1:150, ncol = 5)
z <- matrix(nrow = nrow(x) / 10, ncol = 5)
for (i in 1:5) {
for (j in 1:(nrow(x) / 10)) {
k = (j - 1) * 10 + 1;
z[j, i] <- sum(x[k:(k+9), i])
}
}
x
[,1] [,2] [,3] [,4] [,5]
[1,] 1 31 61 91 121
[2,] 2 32 62 92 122
[3,] 3 33 63 93 123
[4,] 4 34 64 94 124
[5,] 5 35 65 95 125
[6,] 6 36 66 96 126
[7,] 7 37 67 97 127
[8,] 8 38 68 98 128
[9,] 9 39 69 99 129
[10,] 10 40 70 100 130
[11,] 11 41 71 101 131
[12,] 12 42 72 102 132
[13,] 13 43 73 103 133
[14,] 14 44 74 104 134
[15,] 15 45 75 105 135
[16,] 16 46 76 106 136
[17,] 17 47 77 107 137
[18,] 18 48 78 108 138
[19,] 19 49 79 109 139
[20,] 20 50 80 110 140
[21,] 21 51 81 111 141
[22,] 22 52 82 112 142
[23,] 23 53 83 113 143
[24,] 24 54 84 114 144
[25,] 25 55 85 115 145
[26,] 26 56 86 116 146
[27,] 27 57 87 117 147
[28,] 28 58 88 118 148
[29,] 29 59 89 119 149
[30,] 30 60 90 120 150
z
[,1] [,2] [,3] [,4] [,5]
[1,] 55 355 655 955 1255
[2,] 155 455 755 1055 1355
[3,] 255 555 855 1155 1455
我试过的代码Rcpp如下
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector mySum(NumericMatrix x) {
int ncol = x.ncol();
int nrow = x.nrow();
int outRow = nrow / 10;
int i;
int j;
int k;
Rcpp::NumericMatrix z(outRow, ncol);
for (i = 0; i < ncol; i++) {
for (j = 0; j < outRow; j++) {
k = j * 10;
Rcpp::SubMatrix<REALSXP> sm = x(Range(k, k + 9), i);
Rcpp::NumericMatrix m(sm);
double s = Rcpp::sum(m);
z(j, i) = s;
}
}
return z;
}
但是,由于错误,它没有移动。
请告诉我解决方案。
test.cpp: In function 'Rcpp::NumericVector mySum(Rcpp::NumericMatrix)':
test.cpp:18:59: error: no match for call to '(Rcpp::NumericMatrix {aka Rcpp::Matrix<14>}) (Rcpp::Range, int&)'
在处理矩阵时我更喜欢使用 RcppArmadillo
,原因之一是文档非常好 (http://arma.sourceforge.net/docs.html#accu)。我稍微重写了你的代码,似乎工作正常:
library(RcppArmadillo)
library(Rcpp)
cppFunction("
NumericMatrix mySum(arma::mat x) {
int ncol = x.n_cols;
int nrow = x.n_rows;
int outRow = nrow / 10;
int i, j, k;
NumericMatrix z(outRow, ncol);
for (i = 0; i < ncol; i++) {
for (j = 0; j < outRow; j++) {
k = j * 10;
arma::mat sm = x(arma::span(k, k+9), i);
z(j, i) = arma::accu(sm);
}
}
return z;
}
", depends = "RcppArmadillo")
x <- matrix(1:150, ncol = 5)
mySum(x)
[,1] [,2] [,3] [,4] [,5]
[1,] 55 355 655 955 1255
[2,] 155 455 755 1055 1355
[3,] 255 555 855 1155 1455
实际上,在 base R 中有一个名为 rowsum
的完全矢量化函数,可以非常有效地按组求和(附带说明,R 并不总是很慢,这主要取决于您如何使用它)。
x <- matrix(1:150, ncol = 5)
rowsum.default(x, cumsum(seq_len(nrow(x)) %% 10L == 1L), reorder = FALSE)
# [,1] [,2] [,3] [,4] [,5]
# 1 55 355 655 955 1255
# 2 155 455 755 1055 1355
# 3 255 555 855 1155 1455
它肯定会比 Rcpp
版本慢,但在我的系统上,一个 20MM 行的 5 列矩阵运行不到 3 秒
x <- matrix(seq_len(1e8), ncol = 5)
dim(x)
## [1] 20000000 5
system.time(mySum(x))
# user system elapsed
# 0.72 0.24 0.96
system.time(rowsum.default(x, cumsum(seq_len(nrow(x)) %% 10L == 1L), reorder = FALSE))
# user system elapsed
# 2.77 0.15 2.93
编辑:根据您的评论,在测试您的 真实 数据集时 rowsum
比 更快 14=]版本
x <- matrix(seq_len(62400*4100), ncol = 4100)
dim(x)
## [1] 62400 4100
system.time(mySum(x))
# user system elapsed
# 1.53 1.03 2.57
system.time(rowsum.default(x, cumsum(seq_len(nrow(x)) %% 10L == 1L), reorder = FALSE))
# user system elapsed
# 1.48 0.00 1.50
我想使用 Rcpp 获得以下结果。 当大数据时,R 很慢。 因此,我尝试在 Rcpp 中编码。
x <- matrix(1:150, ncol = 5)
z <- matrix(nrow = nrow(x) / 10, ncol = 5)
for (i in 1:5) {
for (j in 1:(nrow(x) / 10)) {
k = (j - 1) * 10 + 1;
z[j, i] <- sum(x[k:(k+9), i])
}
}
x
[,1] [,2] [,3] [,4] [,5]
[1,] 1 31 61 91 121
[2,] 2 32 62 92 122
[3,] 3 33 63 93 123
[4,] 4 34 64 94 124
[5,] 5 35 65 95 125
[6,] 6 36 66 96 126
[7,] 7 37 67 97 127
[8,] 8 38 68 98 128
[9,] 9 39 69 99 129
[10,] 10 40 70 100 130
[11,] 11 41 71 101 131
[12,] 12 42 72 102 132
[13,] 13 43 73 103 133
[14,] 14 44 74 104 134
[15,] 15 45 75 105 135
[16,] 16 46 76 106 136
[17,] 17 47 77 107 137
[18,] 18 48 78 108 138
[19,] 19 49 79 109 139
[20,] 20 50 80 110 140
[21,] 21 51 81 111 141
[22,] 22 52 82 112 142
[23,] 23 53 83 113 143
[24,] 24 54 84 114 144
[25,] 25 55 85 115 145
[26,] 26 56 86 116 146
[27,] 27 57 87 117 147
[28,] 28 58 88 118 148
[29,] 29 59 89 119 149
[30,] 30 60 90 120 150
z
[,1] [,2] [,3] [,4] [,5]
[1,] 55 355 655 955 1255
[2,] 155 455 755 1055 1355
[3,] 255 555 855 1155 1455
我试过的代码Rcpp如下
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector mySum(NumericMatrix x) {
int ncol = x.ncol();
int nrow = x.nrow();
int outRow = nrow / 10;
int i;
int j;
int k;
Rcpp::NumericMatrix z(outRow, ncol);
for (i = 0; i < ncol; i++) {
for (j = 0; j < outRow; j++) {
k = j * 10;
Rcpp::SubMatrix<REALSXP> sm = x(Range(k, k + 9), i);
Rcpp::NumericMatrix m(sm);
double s = Rcpp::sum(m);
z(j, i) = s;
}
}
return z;
}
但是,由于错误,它没有移动。 请告诉我解决方案。
test.cpp: In function 'Rcpp::NumericVector mySum(Rcpp::NumericMatrix)':
test.cpp:18:59: error: no match for call to '(Rcpp::NumericMatrix {aka Rcpp::Matrix<14>}) (Rcpp::Range, int&)'
在处理矩阵时我更喜欢使用 RcppArmadillo
,原因之一是文档非常好 (http://arma.sourceforge.net/docs.html#accu)。我稍微重写了你的代码,似乎工作正常:
library(RcppArmadillo)
library(Rcpp)
cppFunction("
NumericMatrix mySum(arma::mat x) {
int ncol = x.n_cols;
int nrow = x.n_rows;
int outRow = nrow / 10;
int i, j, k;
NumericMatrix z(outRow, ncol);
for (i = 0; i < ncol; i++) {
for (j = 0; j < outRow; j++) {
k = j * 10;
arma::mat sm = x(arma::span(k, k+9), i);
z(j, i) = arma::accu(sm);
}
}
return z;
}
", depends = "RcppArmadillo")
x <- matrix(1:150, ncol = 5)
mySum(x)
[,1] [,2] [,3] [,4] [,5]
[1,] 55 355 655 955 1255
[2,] 155 455 755 1055 1355
[3,] 255 555 855 1155 1455
实际上,在 base R 中有一个名为 rowsum
的完全矢量化函数,可以非常有效地按组求和(附带说明,R 并不总是很慢,这主要取决于您如何使用它)。
x <- matrix(1:150, ncol = 5)
rowsum.default(x, cumsum(seq_len(nrow(x)) %% 10L == 1L), reorder = FALSE)
# [,1] [,2] [,3] [,4] [,5]
# 1 55 355 655 955 1255
# 2 155 455 755 1055 1355
# 3 255 555 855 1155 1455
它肯定会比 Rcpp
版本慢,但在我的系统上,一个 20MM 行的 5 列矩阵运行不到 3 秒
x <- matrix(seq_len(1e8), ncol = 5)
dim(x)
## [1] 20000000 5
system.time(mySum(x))
# user system elapsed
# 0.72 0.24 0.96
system.time(rowsum.default(x, cumsum(seq_len(nrow(x)) %% 10L == 1L), reorder = FALSE))
# user system elapsed
# 2.77 0.15 2.93
编辑:根据您的评论,在测试您的 真实 数据集时 rowsum
比 更快 14=]版本
x <- matrix(seq_len(62400*4100), ncol = 4100)
dim(x)
## [1] 62400 4100
system.time(mySum(x))
# user system elapsed
# 1.53 1.03 2.57
system.time(rowsum.default(x, cumsum(seq_len(nrow(x)) %% 10L == 1L), reorder = FALSE))
# user system elapsed
# 1.48 0.00 1.50