Проблема, вызывающая ваш segfault, связана с этой строкой
std::string temp = Rcpp::as<std::string>(levels[element]);
Так как R индексируется 1, вам нужно
std::string temp = Rcpp::as<std::string>(levels[element - 1]);
Однако я также заметил, что вы увеличиваете свои счетчики внеправильное место (вам нужно увеличивать строку в самом внутреннем элементе catch и integer вне элементов catch) и требовать операторов продолжения после приращений (в противном случае вы в конечном итоге будете делать неприменимые приращения в дополнение к тому, который вы хотите сделать).Как только вы исправите эти вещи, код запускается в тестовом примере, как и ожидалось (но посмотрите в конце обновления, касающиеся двойных и целых чисел).
guess_vector_type(test_factor)
# [1] "character"
Полный рабочий код
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
//' @title Guess Vector Type
//'
//' @description Function analyses content of a factor vector and attempts to
//' guess the correct type.
//'
//' @param x A vector of factor class.
//'
//' @return A scalar string with class name.
//'
//' @export
//'
// [[Rcpp::export]]
Rcpp::String guess_vector_type(Rcpp::IntegerVector x) {
// Define counters for all types
int num_doubles = 0;
int num_integers = 0;
int num_strings = 0;
// Converted strings
double converted_double;
int converted_integer;
// Get character vector with levels
Rcpp::StringVector levels = x.attr("levels");
// Get integer vector with values
// Rcpp::String type = x.sexp_type();
// Returns integer vector type
// Use iterator: https://teuder.github.io/rcpp4everyone_en/280_iterator.html
for(Rcpp::IntegerVector::iterator it = x.begin(); it != x.end(); ++it) {
// Get [] for vector element
int index = std::distance(x.begin(), it);
// Get value of a specific vector element
int element = x[index];
// Convert to normal string
std::string temp = Rcpp::as<std::string>(levels[element - 1]);
// Try converting to an integer
try
{
converted_integer = std::stoi(temp);
}
catch(...)
{
// Try converting to a doubke
try
{
// Convert to ineteges
converted_double = std::stod(temp);
}
catch(...)
{
++num_strings;
continue;
}
++num_doubles;
continue;
}
++num_integers;
}
// Get max value of three variables
// https://stackoverflow.com/a/2233412/1655567
int max_val;
max_val = num_doubles > num_integers? (num_doubles > num_strings? num_doubles: num_strings): (num_integers > num_strings? num_integers: num_strings);
// Create results storage
Rcpp::String res;
// Check which value is matching max val
if (max_val == num_doubles) {
// Most converted to doubles
res = "double";
} else if (max_val == num_integers) {
res = "integer";
} else {
res = "character";
}
// Return results vector
return res;
}
Updates
Я попробовал это на еще нескольких примерах и обнаружил, что он не работает так, как ожидалось для двойников, поскольку программа способна конвертировать "42.18" в целое число (например).Он четко различает целые / двойные числа и символы, хотя:
test_factor <- as.factor(rep(letters, 3))
guess_vector_type(test_factor)
# [1] "character"
test_factor <- as.factor(1:3)
guess_vector_type(test_factor)
# [1] "integer"
test_factor <- as.factor(c(letters, 1))
guess_vector_type(test_factor)
# [1] "character"
test_factor <- as.factor(c(1.234, 42.1138, "a"))
guess_vector_type(test_factor)
# [1] "integer"
В любом случае, это совершенно отдельная проблема от проблемы, представленной в вопросе, по которой вы можете обратиться к этого стекаСообщение переполнения , например.