在C循环内生长R矩阵

Ist*_*ván 2 c r matrix

我有一个生成一系列数据向量的例程,一次一次迭代.我想找到一种方法来"增长"列表或包含这些向量的矩阵.我试着创建一个列表,

PROTECT( myList = allocVector( VECSXP, 1 ) )
Run Code Online (Sandbox Code Playgroud)

但是有没有办法通过最终推送一个向量元素来增加列表?

另外,我不介意使用矩阵,因为我生成的向量具有相同的长度.

Mar*_*gan 7

Rf_lengthgetsin Rinternals.h; 实施于builtin.c:lengthgets.返回的指针需要被PROTECTed,因此有一种模式

SEXP myList;
PROTECT_INDEX ipx;
PROTECT_WITH_INDEX(myList = allocVector( VECSXP, 1 ), &ipx);
REPROTECT(mylist = Rf_lengthgets(mylist, 100), ipx);
Run Code Online (Sandbox Code Playgroud)

如果一个人根据一些未知的停止条件增加一个列表,那么该方法可能就像在R中一样,预分配和填充后跟扩展; 以下是伪代码:

const int BUF_SIZE = 100;
PROTECT_INDEX ipx;
SEXP myList;
int i, someCondition = 1;

PROTECT_WITH_INDEX(myList=allocVector(VECSXP, BUF_SIZE), &ipx);
for (i = 0; some_condition; ++i) {
    if (Rf_length(myList) == i) {
        const int len = Rf_length(myList) + BUF_SIZE;
        REPROTECT(myList = Rf_lengthgets(mYlist, BUF_SIZE), &ipx);
    }
    PROTECT(result = some_calculation();
    SET_VECTOR_ELT(myList, i, result);           
    UNPROTECT(1);
    // set some_condition
}
Rf_lengthgets(myList, i); // no need to re-PROTECT; we're leaving C
UNPROTECT(1)
return myList;
Run Code Online (Sandbox Code Playgroud)

这会执行深层复制myList,因此可能会变得昂贵,并且在某种程度上如果目标是评估some_calculation,那么在R循环中执行预分配和扩展操作似乎更容易且效率也不会太低some_calculation并在循环内进行赋值.


Dir*_*tel 6

这是恕我直言,这是C++击败C牌的好例子.

在C++中,您可以使用STL容器(例如矢量)并使用一次一个地轻松插入元素push_back().你永远不会使用mallocfree(newdelete),你永远不会触摸指针.在C中没有办法做到这一点.

同样,您可以使用R和C++之间的Rcpp接口,这使得您在C++中增长的数据更容易获得.