Как бороться с факторами в Rcpp - PullRequest
1 голос
/ 12 апреля 2019

Я пытаюсь узнать, как использовать Rcpp в R. Может кто-нибудь указать, в чем проблема с этим кодом.Вероятно, существует более одной проблемы.

Когда объект c вводится в fun() в нижней части кода, я хочу, чтобы он выводил вектор / массив со значениями "Home", "Elsewhere"или «Число».

Я нахожу здесь тип данных немного запутанным.Мой оригинальный набор данных является фактором.Если я положу это в storage.mode(), то вернется integerТогда я предполагаю, что должен назначить аргумент x как IntegerVector.Это смущает меня, потому что данные содержат буквы, то есть "H" и "E", так как же данные могут быть целыми числами?Когда я говорю == «H» в выражении if, я не знаю, понимает ли оно, что я говорю.


library(Rcpp)

c <- factor(c("E", "H", "E", "12", "10", "60", "80", "11", "H", "H"))
class(c)
storage.mode(c)

cppFunction(' IntegerVector fun(IntegerVector x){

            // creates an empty character vector the size/length of x.
            CharacterVector y = x.size() ;


            int n = x.size() - 1 ;


            //loop
            for(int i = 0; i <= n; i = i + 1){

            if(x[i] == "H"){
            y[i] = "Home" ;

            }else if(x[i] == "E"){
            y[i] = "Elsewhere" ;
            }else{
            y[i] = "Number" ;
            } ;


            }



            return y ;

            }')


fun(c)

1 Ответ

4 голосов
/ 12 апреля 2019

Примечание: повсюду я буду ссылаться на f, а не c.Неправильно называть переменные тем же именем, что и встроенная функция или константа, например c, T или F.Поэтому я изменяю начало вашего кода следующим образом:

library(Rcpp)

f <- factor(c("E", "H", "E", "12", "10", "60", "80", "11", "H", "H"))

Помимо просмотра class(f) и storage.mode(f), полезно взглянуть на str(f):

str(f)
# Factor w/ 7 levels "10","11","12",..: 6 7 6 3 1 4 5 2 7 7

По правде говоря, фактор - это целочисленный вектор с «уровнями»: символьный вектор, соответствующий каждому уникальному целочисленному значению.К счастью, вы можете получить это из C ++, используя .attr() функцию-член Rcpp::IntegerVector:

cppFunction('CharacterVector fun(IntegerVector x){

            // creates an empty character vector the size/length of x.
            CharacterVector y = x.size() ;

            // Get the levels of x
            CharacterVector levs = x.attr("levels");

            int n = x.size() - 1 ;


            //loop
            for(int i = 0; i <= n; i = i + 1){

            if(levs[x[i]-1] == "H"){
            y[i] = "Home" ;

            }else if(levs[x[i]-1] == "E"){
            y[i] = "Elsewhere" ;
            }else{
            y[i] = "Number" ;
            } ;


            }



            return y ;

            }')

fun(f)
# [1] "Elsewhere" "Home"      "Elsewhere" "Number"    "Number"    "Number"   
# [7] "Number"    "Number"    "Home"      "Home" 

Итак, чтобы получить то, что вы хотите, вам пришлось сделать три вещи:

  1. Измените тип возвращаемого значения с IntegerVector на CharacterVector (хотя вы были совершенно правы, что ввод должен быть IntegerVector)
  2. Получите уровни коэффициента, используя CharacterVector levs = x.attr("levels");
  3. Сравните levs[x[i]-1] с "H" и т. Д., А не x[i] - x[i] всегда будет целым числом, давая элемент вектора уровней, которому он соответствует.Мы делаем -1, поскольку C ++ индексируется 0, а R индексируется 1.

Другие примечания:

Как вы говорите, ясно, что "[вы] пытаюсь научиться использовать Rcpp () в R. "Вам определенно захочется потратить некоторое время на такие ресурсы, как Rcpp для всех (это глава о факторах), Rcpp Gallery (эта конкретная ссылка - статья о факторах), Глава Хэдли о Rcpp , и определенно виньетки Rcpp, доступные здесь .

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