如何处理Rcpp中的因素

How to deal with factors in Rcpp

我正在尝试学习如何在 R 中使用 Rcpp。有人可以指出 用这段代码找出 problem/s 是什么。可能不止一个 问题。

当在代码底部将 c 对象输入 fun() 时,我希望它输出 vector/array 值 "Home"、"Elsewhere" 或 "Number".

我发现这里的数据类型有点令人困惑。我的原始数据集是一个因素。如果我将其放入 storage.mode() 中,它会 returns integer。我假设我必须将 x 参数分配为 IntegerVector。这让我很困惑,因为数据包含字母,即 "H" 和 "E",那么数据怎么可能是整数呢? 当我在 if 语句中说 == "H" 时,我不知道它是否理解我在说什么。


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)

注意:自始至终,我指的是 f,而不是 c。将变量命名为与内置函数或常量相同的名称是不好的做法,例如 cTF。因此,我将代码的开头更改如下:

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

事实上,一个因子是一个整数向量,"levels":一个对应于每个唯一整数值​​的字符向量。幸运的是,您可以使用 Rcpp::IntegerVector:

.attr() 成员函数从 C++ 中获取它
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. 将 return 类型从 IntegerVector 更改为 CharacterVector(尽管您完全正确地认为输入应该是 IntegerVector
  2. 使用 CharacterVector levs = x.attr("levels");
  3. 获取因子水平
  4. 比较 levs[x[i]-1]"H" 等,而不是 x[i] -- x[i] 将始终是一个整数,给出水平向量的元素对应。我们做 -1 因为 C++ 是 0 索引而 R 是 1 索引。

其他说明:

很明显,正如您所说,“[您] 正在尝试学习如何在 R 中使用 Rcpp()。”您肯定会想花一些时间在 Rcpp for Everyone (that's the chapter on factors), the Rcpp Gallery (this specific link is an article on factors), Hadley's chapter on Rcpp, and definitely the Rcpp vignettes available here.

等资源上