2013-03-31 9 views
12

patrząc na dokumentację rcpp i Rcpp::DataFrame w galerii zdałem sobie sprawę, że nie wiem jak modyfikować DataFrame przez odniesienie. Googling nieco znalazłem ten post na SO i ten post w archiwum. Nie ma nic oczywistego, więc podejrzewam, że tęsknię za czymś wielkim: "Tak już jest, ponieważ" lub "to nie ma sensu, ponieważ".Przechodząc przez odniesienie do data.frame i aktualizując go za pomocą rcpp

Próbowałem następujących który skompilowany ale obiekt data.frame przekazane updateDFByRef w R przebywał nietknięte

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
void updateDFByRef(DataFrame& df) { 
    int N = df.nrows(); 
    NumericVector newCol(N,1.); 
    df["newCol"] = newCol; 
    return; 
} 
+6

Już opublikowałeś na liście. Dlaczego repostujesz tutaj? –

Odpowiedz

12

Sposób DataFrame::operator[] realizowany jest rzeczywiście Leeds kopią kiedy to zrobić:

df["newCol"] = newCol; 

Aby zrobić to, co chcesz, trzeba rozważyć, co ramka danych jest lista wektorów, z pewnymi atrybutami . Następnie możesz pobrać dane z oryginału, kopiując wektory (wskaźniki, a nie ich zawartość).

Coś takiego jak to jest. To trochę więcej pracy, ale nie aż tak trudne.

// [[Rcpp::export]] 
List updateDFByRef(DataFrame& df, std::string name) { 
    int nr = df.nrows(), nc= df.size() ; 
    NumericVector newCol(nr,1.); 
    List out(nc+1) ; 
    CharacterVector onames = df.attr("names") ; 
    CharacterVector names(nc + 1) ; 
    for(int i=0; i<nc; i++) { 
     out[i] = df[i] ; 
     names[i] = onames[i] ; 
    } 
    out[nc] = newCol ; 
    names[nc] = name ; 
    out.attr("class") = df.attr("class") ; 
    out.attr("row.names") = df.attr("row.names") ; 
    out.attr("names") = names ; 
    return out ; 
} 

Istnieją problemy związane z tym podejściem. Oryginalna ramka danych i ta, którą utworzyłeś, mają te same wektory i dlatego mogą się zdarzyć złe rzeczy. Używaj tego tylko, jeśli wiesz, co robisz.

+0

Dziękuję bardzo, teraz jest jaśniej, myślę, że brakowało mi podstawowej wiedzy, na przykład, że 'SEXP' było już referencjami. Zajrzę do http://cran.r-project.org/doc/manuals/r-release/R-ints.pdf. Na razie "przygotowywałam" plik 'data.table' w R dodając dodatkową kolumnę i aktualizowałam ją w Rcpp, więc żadna kopia (chyba) nie została wykonana. O wiele lepiej, rozumiem ryzyko, ale to jest w porządku dla tego, co robię. Merci beaucoup. – statquant

+0

Po raz kolejny, jesteś po prostu w błędzie: _Myślę, że brakowało mi podstawowej wiedzy, jak to, że SEXP było już referencjami_. Nie odniesienia, ale wskazówki. Spróbuj sprawdzić, co oznacza ostatnia litera w SEXP. –

3

krótkim odpowiedź brzmi „bo to nie ma sensu”.

A data.frame jest w zasadzie listą wektorów. Kilka sekund refleksji wyjaśnia, że ​​dodanie nowej kolumny do tej listy pociąga za sobą kopię. Więc zmienilibyście swoją zmienną df w tym przykładzie, nie zwracajcie jej, a zatem pomińcie modyfikację.

Samo pragnienie czegoś do pracy w określony sposób nie zawsze jest wystarczające.

+0

Zastępując 'void' przez' SEXP' na przykład 'return df;' zrobi lewy? – agstudy

+0

Tak, zrobi to dowolny z SEXP, Rcpp :: List lub Rcpp :: DataFrame. Obecnie wydaje się, że powracamy jako lista, więc wydajemy się tracić dane.frame-ność tego. –

+0

dzięki .. Po prostu przetestuję i działa jak urok! Dodanie 'as.data.frame' do wyniku daje mi pożądane dane.frame-ness ... – agstudy

Powiązane problemy