2016-07-19 13 views
3

Mein Rcpp-Code schlägt gelegentlich aus (SEGFAULT, etc.) aus Gründen, die ich nicht verstehe. Der Code erstellt einen großen data.frame und versucht dann, eine Teilmenge dieses data.frames durch Aufrufen der R-Teilmengenfunktion [.data.frame aus derselben Methode zu erhalten, mit der der Rahmen erstellt wird. Eine sehr vereinfachte Version davon ist unten dargestellt:Vermeiden Sie SIGSEGV beim Subsetting von data.frame mit Aufruf von `[data.frame` in Rcpp

library(Rcpp) 
src <- '// R function to subset data.frame - what will be called to subset 
DataFrame test() { 
Function subsetinR("[.data.frame"); 

// Make a dataframe in Rcpp to subset 
size_t n = 100; 
auto df = DataFrame::create(Named("a") = std::vector<double> (n, 2.0), 
          Named("b") = std::vector<double> (n, 4.0)); 

// Now make a vector to subset with 
LogicalVector filter = LogicalVector::create(n, TRUE); 
for (size_t i =0; i < n; i++) { 
    if (i % 2 == 0) filter[i] = FALSE; 
} 

// Subset, here is where it fails! 
df = subsetinR(df, filter, R_MissingArg); 
return df; 
}' 

fun <- cppFunction(plugins=c("cpp11"), src, verbose = TRUE, depends="Rcpp") 
fun() 

Doch während dies gelegentlich funktioniert, wird es andere Zeiten ist es nicht mit dem folgenden Fehler:

*** caught segfault *** 
    address 0x7ff700000030, cause 'memory not mapped'` 

Wer weiß, was falsch läuft?

Hinweis: Dies ist kein Duplikat. Ich habe andere Stapelüberlauf-Antworten gesehen, die Vektoren erzeugen, indem eine Teilmenge auf jedem Vektor, z.B.

// Next up, create a new DataFrame Object with selected rows subset. 
    return Rcpp::DataFrame::create(Rcpp::Named("val1") = val1[idx], 
           Rcpp::Named("val2") = val2[idx], 
           Rcpp::Named("val3") = val3[idx], 
           Rcpp::Named("val3") = val4[idx] 
           ); 

Aber ich bin auf der Suche explizit das wiederholte [idx] subsetting zu vermeiden, da die idx nicht bekannt ist, wenn die data.frame aufgebaut sind (es erst am Ende bekannt ist), und ich bin die Hoffnung, eine finden Art und Weise, die nicht wiederholt das aufrufen bedeutet. Wenn es möglich ist, den data.frame am Ende mit einem Durchlauf zu transformieren, würde das gut funktionieren.

+1

Zweitens * nicht * verwenden Sie die Teilmenge Funktion in * R *. Versuchen Sie stattdessen, den integrierten Subindex für 'Rcpp :: * Vectors []' zu verwenden. – coatless

+0

Wie @coatless ruhig gesagt, C++! = R, so dass Ihr erster Aufruf des Eintrags aus C++ wahrscheinlich keine R-Funktion sein sollte. In erster Näherung: Wenn Sie den R-Code verwenden, erhalten Sie die R-Geschwindigkeit. –

+0

@ Coatless Danke für den Kommentar. Ich habe die frühere Frage gesehen, die du als Duplikat markiert hast, aber das hat mein Problem leider nicht gelöst. Ich versuche tatsächlich, die [] Teilmengenoperation für jeden Vektor spezifisch zu vermeiden, weil es zehn Spalten im Vektor gibt, die geladen werden können oder nicht, und das Schreiben von 'df [" etwas "] = etwas [idx] schien viel weniger stabil als nur einmal zu schreiben. – evolvedmicrobe

Antwort

2

Das Problem hier ist, dass LogicalVector::create() nicht tut, was Sie hier erwarten - es gibt einen Vektor der Länge zwei, mit den Elementen TRUE und TRUE. Mit anderen Worten: Ihr Code:

LogicalVector filter = LogicalVector::create(n, TRUE);

erzeugt keinen logischen Vektor der Länge n mit Werten TRUE, sondern eine logische Vektor der Länge zwei mit dem ersten Elemente ‚truthy‘ und so TRUE zu sein, und die zweiten ausdrücklich TRUE.

Wahrscheinlich wollten Sie nur den regulären Konstruktor verwenden, z. LogicalVector(n, TRUE).

Verwandte Themen