I wrote this R function that, given any number of vectors (...) combines them by summing the respective element values based on their names.
add_vectors <- function(...) {
a <- list(...)
nms <- sort(unique(unlist(lapply(a, names))))
out <- numeric(length(nms))
names(out) <- nms
for (v in a) out[names(v)] <- out[names(v)] + v
out
}
Example:
v1 <- c(a=2,b=3,e=4)
v2 <- c(b=1,c=6,d=0,a=4)
add_vectors(v1, v2)
#
a b c d e
6 4 6 0 4
I'm trying to write an equivalent function which is much faster.
Unfortunately at the moment I have no idea how to achieve this in R so I thought to Rcpp.
But, in order to convert in Rcpp this function I miss some concepts:
... parameter. With a parameter of List type in Rcpp ?... parameter.R, but I cannot figure how to do in Rcpp).So I'm looking for someone that can help me to improve the performances of this function (in R or Rcpp, or both).
Any help is appreciated, thanks.
I would use something like this:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector add_all(List vectors){
RCPP_UNORDERED_MAP<std::string,double> out ;
int n = vectors.size() ;
for( int i=0; i<n; i++){
NumericVector x = vectors[i] ;
CharacterVector names = x.attr("names") ;
int m = x.size() ;
for( int j=0; j<m; j++){
String name = names[j] ;
out[ name ] += x[j] ;
}
}
return wrap(out) ;
}
with the following wrapper:
add_vectors_cpp <- function(...){
add_all( list(...) )
}
RCPP_UNORDERED_MAP being just a typedef to unordered_map, either in std:: or in std::tr1:: depending on your compiler, etc ...
The trick here is to create a regular list out of the ... using the classic list(...).
If you really wanted to pass down directly ... in C++ and deal with it internally, you would have to use the .External interface. This is very rarely use, so Rcpp attributes don't support the .External interface.
With .External, it would look like this (untested):
SEXP add_vectors(SEXP args){
RCPP_UNORDERED_MAP<std::string,double> out ;
args = CDR(args) ;
while( args != R_NilValue ){
NumericVector x = CAR(args) ;
CharacterVector names = x.attr("names") ;
int m = x.size() ;
for( int j=0; j<m; j++){
String name = names[j] ;
out[ name ] += x[j] ;
}
args = CDR(args) ;
}
return wrap(out) ;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With