Передача по ссылке data.frame и ее обновление с помощью rcpp

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

Я попробовал следующее, скомпилированный, но объект 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;
}

Ответ 1

Способ 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 ;
}

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

Ответ 2

Краткие ответы - "потому что это не имеет смысла".

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

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