2016-04-12 10 views
1

Angenommen, ich habe eine vector<int> positions, die Positionen darstellt, die ich möchte Teilmenge aus, und zwei Rcpp::NumericVector Vektoren A und B, die ich möchte Teilmenge (beide können auch als vector<double> behandelt werden).Was ist der beste Weg, um eine Funktion auf eine Teilmenge eines Vektors anzuwenden?

Was wäre der beste Weg, was in R zu berechnen ich als sum(A[positions]) (ein double) schreiben würde, oder A[positions]/B[positions] (a vector[double])? Grundsätzlich möchte ich auf die Elemente der Vektoren an bestimmten Positionen zugreifen, ohne Kopien (oder eine for Schleife), wenn ich nicht muss.

Beispiel in R:

positions = c(2,4,5) # just a vector with positions 
A = rnorm(100) # a vector with 100 random numbers 
B = rnorm(100) 

mysum <- sum(A[positions]) 
mysmallvector <- A[positions]/B[positions] # or (A/B)[positions] 

Gerade jetzt alles, was ich die Werte von positions nur Schleife durch und und die Vektoren von Position eins nach dem anderen Teilmenge, aber ich kann es eine elegantere Lösung des Gedankens nicht erwehren .

+0

einer for-Schleife Vermeidung nicht möglich ist: Sie durch Ihre Sammlung iterieren haben. Das tut R auch hinter den Kulissen. Wenn Sie auf der anderen Seite eine elegantere API möchten, müssen Sie auf Ihre eigenen Klassen zurückgreifen oder eine C++ - Matrixbibliothek verwenden, von der es viele gibt. – OnMyLittleDuck

Antwort

2

Also Replikation der R-Funktionalität in Rcpp ist nicht unbedingt ideal. Zum einen sollten Sie auf jeden Fall die Vorbehalte zu subsetting in Rcpp mit Rcpp Zucker Ausdrücke überprüfen. Zweitens verwenden Sie eine for Schleife sogar innerhalb von R aufgrund der Vektorisierungsstruktur R hat.

Möglicherweise möchten Sie anstelle von Rcpp-Datentypen RcppArmadillo verwenden. Der Nachteil hierbei ist, dass Sie einen Kopiertreffer erleiden, wenn die Daten in C++ und dann wieder in R portiert werden. Mit Rcpp-Datentypen vermeiden Sie das, aber Sie müssen eigene Operationen definieren (siehe divate_subset() unten)).

Mit diesem wird gesagt, wir die Funktionalität über RCPP angefordert replizieren können:

#include <Rcpp.h> 
using namespace Rcpp; 

// Uses sugar index subsets 
// [[Rcpp::export]] 
NumericVector subset(NumericVector x, IntegerVector idx) { 
    return x[idx]; 
} 

// Uses sugar summation function (e.g. a nice for loop) 
// [[Rcpp::export]] 
double sum_subset(NumericVector x, IntegerVector idx) { 
    return sum(subset(x,idx)); 
} 

// No sugar for element-wise division 
// [[Rcpp::export]] 
NumericVector divide_subset(NumericVector x, NumericVector y, IntegerVector idx) { 
    unsigned int n = idx.size(); 
    NumericVector a(n); 
    for(unsigned int i = 0; i < idx.size(); i++){ 
    a[i] = x[idx[i]]/y[idx[i]]; 
    } 

    return a; 
} 


/*** R 
set.seed(1334) 
positions = c(2,4,5) 

# Subtract one from indexes for C++ 
pos_cpp = positions - 1 

A = rnorm(100) # a vector with 100 random numbers 
B = rnorm(100) 

mysum = sum(A[positions]) 

cppsum = sum_subset(A, pos_cpp) 
all.equal(cppsum, mysum) 

mysmallvector = A[positions]/B[positions] # or (A/B)[positions] 

cppdivide = divide_subset(A,B, pos_cpp) 
all.equal(cppdivide, mysmallvector) 
*/