2016-07-19 3 views
3

Мой код Rcpp иногда терпит неудачу (SEGFAULT и т. Д.) По причинам, которые я не понимаю. Код создает большой файл data.frame, а затем пытается получить подмножество этого data.frame, вызывая функцию подмножества R, [.data.frame), из того же метода, который создает фрейм. Очень упрощенная версия этого показано ниже:Избегайте SIGSEGV при подмножестве data.frame с вызовом `[data.frame` в Rcpp

library(Rcpp) 
src <- '// R function to subset data.frame - what will be called to subset 
DataFrame test() { 
Function subsetinR("[.data.frame"); 

// Make a dataframe in Rcpp to subset 
size_t n = 100; 
auto df = DataFrame::create(Named("a") = std::vector<double> (n, 2.0), 
          Named("b") = std::vector<double> (n, 4.0)); 

// Now make a vector to subset with 
LogicalVector filter = LogicalVector::create(n, TRUE); 
for (size_t i =0; i < n; i++) { 
    if (i % 2 == 0) filter[i] = FALSE; 
} 

// Subset, here is where it fails! 
df = subsetinR(df, filter, R_MissingArg); 
return df; 
}' 

fun <- cppFunction(plugins=c("cpp11"), src, verbose = TRUE, depends="Rcpp") 
fun() 

Однако, в то время как это иногда работает, это будет другой раз он терпит неудачу со следующей ошибкой:

*** caught segfault *** 
    address 0x7ff700000030, cause 'memory not mapped'` 

Каждый знает, что происходит не так?

Примечание: Это не дубликат. Я видел другие ответы переполнения стека, которые создают векторы, используя подмножество для каждого вектора, например.

// Next up, create a new DataFrame Object with selected rows subset. 
    return Rcpp::DataFrame::create(Rcpp::Named("val1") = val1[idx], 
           Rcpp::Named("val2") = val2[idx], 
           Rcpp::Named("val3") = val3[idx], 
           Rcpp::Named("val3") = val4[idx] 
           ); 

Однако, я явно ищет, чтобы избежать повторного [idx] Подменю, как IDX не известно, когда data.frame строится (известно только в конце), и я надеюсь найти который не требует многократного вызова этого. Если можно преобразовать data.frame в конце с одним ходом, это будет работать нормально.

+1

Во-вторых, do * not * используйте функцию подмножества в * R *. Вместо этого попробуйте использовать встроенный индекс подмножества для 'Rcpp :: * Vectors []'. – coatless

+0

Как @coatless спокойно заявлено, C++! = R, поэтому ваш первый вызов записи из C++, вероятно, не должен быть функцией R. В первом приближении: если вы используете R-код, вы получаете R-скорость. –

+0

@Coatless Спасибо за комментарий. Я видел более ранний вопрос, который вы отметили как дубликат, но, к сожалению, это не решило мою проблему. Я на самом деле пытаюсь конкретно избегать операции подмножества [] для каждого вектора, потому что в векторе есть 10 столбцов, которые могут быть загружены или не загружены, а запись 'df [" something "] = something [idx]' казалась очень менее устойчив, чем просто писать его один раз. – evolvedmicrobe

ответ

2

Проблема здесь в том, что LogicalVector::create() не делает то, что вы ожидаете здесь, - это возвращает вектор длины два, с элементами TRUE и TRUE. Другими словами, ваш код:

LogicalVector filter = LogicalVector::create(n, TRUE);

генерирует не логический вектор длины n со значениями TRUE, но вместо того, чтобы логический вектор длины два с первым элементом является «truthy» и так TRUE, а второй явно TRUE.

Вероятно, вы хотите использовать обычный конструктор, например. LogicalVector(n, TRUE).

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