Выращивание матрицы R внутри петли C - PullRequest
2 голосов
/ 18 сентября 2011

У меня есть подпрограмма, которая генерирует серию векторов данных, по одной итерации за раз. Я хотел бы найти способ «вырастить» либо список, либо матрицу, содержащую эти векторы. Я пытался создать список,

PROTECT( myList = allocVector( VECSXP, 1 ) )

Но есть ли способ увеличить список, нажав на элемент вектора в конце?

Кроме того, я не возражаю против использования матрицы, поскольку генерируемые мной векторы имеют одинаковую длину.

Ответы [ 2 ]

7 голосов
/ 18 сентября 2011

Rf_lengthgets в Rinternals.h; реализовано в builtin.c:lengthgets. Возвращаемый указатель должен быть ЗАЩИЩЕН, поэтому один шаблон

SEXP myList;
PROTECT_INDEX ipx;
PROTECT_WITH_INDEX(myList = allocVector( VECSXP, 1 ), &ipx);
REPROTECT(mylist = Rf_lengthgets(mylist, 100), ipx);

Если бы кто-то увеличивал список на основе некоторого неизвестного условия остановки, подход мог бы быть таким же, как в 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;

Это выполняет глубокое копирование myList, поэтому может стать дорогостоящим и в некоторых отношениях, если у него есть цель оценить some_calculation, то кажется, что проще и не слишком менее эффективно выполнять операции предварительного выделения и расширения в цикле R, вызывая some_calculation и выполняя присваивание внутри цикла.

6 голосов
/ 18 сентября 2011

Это ИМХО хороший пример того, где C ++ опережает C.

В C ++ вы можете использовать контейнер STL (например, vector) и легко вставлять элементы по одному, используя push_back().Вы никогда не используете malloc или free (или new и delete) и никогда не трогаете указатели.В C.

просто нет способа сделать это. Кроме того, вы можете использовать интерфейс Rcpp между R и C ++, который позволяет передавать данные, которые вы выросли в C ++, вR намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...