R быстрая матрица cbind с использованием Rcpp

cbind в R относительно много времени при повторных вызовах, но это также мощный для различных типов данных.
Я написал код, который в 3 раза быстрее, чем cbind при связывании двух матриц. Но bind_cols в dplyr пакет просто в 100 раз быстрее, чем cbind, Жаль только, что он не может принять матрицу в качестве входных данных. Может кто-нибудь сделать код ниже более быстрым. Кроме того, как я могу быстро связать разреженную матрицу? Вот код, который я использовал:

require( Rcpp )

func <- 'NumericMatrix mmult(NumericMatrix a,NumericMatrix b) {
//the colnumber of first matrix
int acoln=a.ncol();
//the colnumber of second matrix
int bcoln=b.ncol();
//build a new matrix, the dim is a.nrow() and acoln+bcoln
NumericMatrix out(a.nrow(),acoln+bcoln) ;
for (int j = 0; j < acoln + bcoln; j++) {
if (j < acoln) {
out(_,j) = a(_,j);
} else {
//put the context in the second matrix to the new matrix
out(_,j) = b(_,j-acoln);
}
}
return out ;
}'

a <- matrix(rep(1,2000*100),2000)
b <- matrix(rep(2,2000*10),2000)

cppFunction(func)

system.time(for (i in seq(1,800)) {mmult(a,b)})
system.time(for (i in seq(1,800)) {cbind(a,b)})
identical(mmult(a,b),cbind(a,b))

8

Решение

Заимствование идеи из этого комментарий Ромэн Франсуа в одном из моих предыдущих приключений Rcpp,

func1 <- 'NumericMatrix mmult1(NumericMatrix a, NumericMatrix b) {
int acoln = a.ncol();
int bcoln = b.ncol();
NumericMatrix out = no_init_matrix(a.nrow(), acoln + bcoln);
for (int j = 0; j < acoln + bcoln; j++) {
if (j < acoln) {
out(_, j) = a(_, j);
} else {
out(_, j) = b(_, j - acoln);
}
}
return out;
}'

cppFunction(func1)
set.seed(42)
a <- matrix(rnorm(1e7), 1e3)
b <- matrix(runif(1e7), 1e3)

identical(mmult(a, b), mmult1(a, b))
#TRUE

library(microbenchmark)
microbenchmark(mmult(a, b),
mmult1(a, b),
cbind(a, b),
times = 10)

#Unit: milliseconds
#         expr    min     lq   mean median    uq   max neval
#  mmult(a, b)  69.64  70.52  89.71  72.28 128.8 136.6    10
# mmult1(a, b)  50.84  50.95  69.65  51.43 111.6 114.4    10
#  cbind(a, b) 192.35 194.67 201.13 195.30 196.1 255.9    10

Ничего страшного, но и неплохо для такого тривиального изменения.

6

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector