2013-03-31 21 views
12

rcpp belgelerine ve Rcpp::DataFrame galeriye baktığımda, bir DataFrame'i nasıl referans göstererek değiştireceğimi bilmiyordum. Biraz googling bu yazıyı SO üzerinde ve bu yazıyı arşivde buldum. Açık hiçbir şey yok, bu yüzden "Bu zaten zaten böyle bir şey" veya "mantıklı değil çünkü" gibi büyük bir şeyi özlediğimden şüpheleniyorum. Bir data.frame referansı ile geçerek ve rcpp ile güncelleme yaparak

Ben derlenmiş aşağıdaki çalıştı ama R updateDFByRef geçirilen data.frame nesne "hiçbir mantıklı nedeni" dir bakir

#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

Zaten listeye gönderildiniz. Neden burada yayınlanıyorsun? –

cevap

12

yolu DataFrame::operator[] gerçekten kopyasına leeds uygulanır:

df["newCol"] = newCol; 

istediğini yapmak için, bir veri çerçevesi belli özelliklere sahip, vektörlerin listesidir dikkate almak gerekir . Daha sonra, orijinalleri (vektörleri) (içeriklerini değil, işaretçileri) kopyalayarak verileri çekebilirsiniz.

Böyle bir şey böyle yapar. Biraz daha fazla iş, ama o kadar da zor değil.

// [[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 ; 
} 

Bu yaklaşımla ilgili sorunlar var. Orijinal veri çerçeveniz ve oluşturduğunuz, aynı vektörleri paylaşır ve çok kötü şeyler olabilir. Bu yüzden sadece ne yaptığını biliyorsan bunu kullan.

+0

Çok teşekkür ederim, şimdi daha açık, sanırım ben 'SEXP' zaten referanslar olduğu gibi temel bilgi eksikti. Http://cran.r-project.org/doc/manuals/r-release/R-ints.pdf adresine bir göz atacağım. Şimdilik, R'de ek bir sütun ekleyerek ve Rcpp içerisinde güncellediğimde "data.table" ı "hazırlıyordum", bu yüzden hiçbir kopya (bence) yapılmadı. Bu çok daha iyi, bunu yaparken riskleri anlıyorum ama yaptığım şey için iyi. Merci beaucoup. – statquant

+0

Bir kez daha, yanlış anlıyorsunuz: Sanırım SEXP'nin zaten referansları olduğu gibi temel bilgileri kaçırıyordum. Referanslar değil, işaretçiler. SEXP'deki son harfin ne anlama geldiğini araştırmaya çalışın. –

3

kısa cevaplar kaldı. Bir data.frame

A data.frame temelde vektörlerin bir listesidir. Birkaç saniyelik yansıma, bu listeye yeni bir sütun eklemenin bir kopya gerektirdiğini açıkça ortaya koymaktadır. Yani, örneğinizde df değişkeninizi değiştirirsiniz, geri göndermezsiniz ve dolayısıyla değişikliği kaybedersiniz.

Sadece belirli bir şekilde çalışmak için bir şey istemek her zaman yeterli değildir. Bunu yaparken

+0

Bu nedenle "void" ifadesini "SEXP" ile değiştirmek, örneğin bir "return df", hile yapacak mı? – agstudy

+0

Evet, SEXP, Rcpp :: List veya Rcpp :: DataFrame öğelerinden herhangi biri yapacaktır. Şu anda bir liste olarak geri geliyor gibi görünüyor, bu yüzden biz data.frame-ness kaybetmek gibi görünüyor. –

+0

teşekkürler ... Sadece test et ve bir çekicilik gibi çalışıyor! Sonuç olarak 'as.data.frame' eklendiğinde bana istenen data.frame-ness değeri veriliyor ... – agstudy

İlgili konular