2013-03-31 2 views
12

, глядя на документацию rcpp и Rcpp::DataFrame в галерее. Я понял, что не знаю, как изменить DataFrame по ссылке. Попутно я нашел этот пост на SO и этот пост в архиве. Нет ничего очевидного, поэтому я подозреваю, что пропущу нечто вроде «Это уже так, потому что» или «это не имеет смысла, потому что».Переходя по ссылке data.frame и обновляя его с помощью rcpp

Я попытался следующие, скомпилированные но data.frame объект передается в updateDFByRef R остались нетронутыми

#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

Вы уже разместили сообщение в списке. Почему вы здесь переплачиваете? –

ответ

12

Путь DataFrame::operator[] реализуется действительно Лидс копии, когда вы делаете что:

df["newCol"] = newCol; 

Чтобы сделать то, что вы хотите, вы должны учитывать, что кадр данных, список векторов, с определенными атрибутами , Затем вы можете захватывать данные из оригинала, копируя векторы (указатели, а не их содержимое).

Что-то вроде этого. Это немного больше работы, но не так сложно.

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

Есть проблемы, связанные с этим подходом. Ваш исходный фрейм данных и тот, который вы создали, используют одни и те же векторы, и поэтому могут произойти такие плохие вещи. Поэтому используйте это, только если вы знаете, что делаете.

+0

Большое спасибо, теперь яснее, я думаю, что мне не хватало базовых знаний, таких как факт, что «SEXP» уже были ссылками. Я посмотрю на http://cran.r-project.org/doc/manuals/r-release/R-ints.pdf. На данный момент я «готовлю» 'data.table' в R, добавляя дополнительный столбец и обновляя его в Rcpp, поэтому копия (я думаю) не была выполнена. Это намного лучше, я понимаю риски, которые делают это, но это нормально для того, что я делаю. Merci beaucoup. – statquant

+0

Еще раз, вы просто ошибаетесь: _Я думаю, что мне не хватало базовых знаний, таких как тот факт, что SEXP уже были ссылками. Не ссылки, а указатели. Попробуйте посмотреть, что означает последнее письмо в SEXP. –

3

Короткий ответ «потому что это не имеет никакого смысла».

A data.frame по существу является списком векторов. Несколько секунд отражения дают понять, что добавление нового столбца в этот список влечет за собой копию. Таким образом, вы изменяете переменную df в примере, не возвращайте ее и, следовательно, теряете ее.

Просто желая, чтобы что-то работало определенным образом, не всегда достаточно.

+0

Итак, заменив 'void' на' SEXP', например, 'return df;' выполнит трюк? – agstudy

+0

Да, любой из SEXP, Rcpp :: List или Rcpp :: DataFrame будет делать. В настоящее время, похоже, возвращается как список, поэтому мы, похоже, теряем данные. –

+0

спасибо .. Я просто тестирую его, и он работает как шарм! Добавление 'as.data.frame' в результат даст мне нужные данные.frame-ness ... – agstudy

Смежные вопросы