如何处理Rcpp中的因素

Ste*_*eve 2 r rcpp

我正在尝试学习如何在 R 中使用 Rcpp。有人可以指出这段代码的问题所在。问题可能不止一个。

当在代码底部c输入对象fun()时,我希望它输出一个向量/数组,其值为“Home”、“Elsewhere”或“Number”。

我发现这里的数据类型有点令人困惑。我的原始数据集是一个因素。如果我把它放进去storage.mode()它会返回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)
Run Code Online (Sandbox Code Playgroud)

duc*_*ayr 5

注意:在整个过程中,我将参考f,而不是c。这是不好的做法,名称变量同名内建函数或常量,例如cTF。因此,我将代码的开头更改如下:

library(Rcpp)

f <- factor(c("E", "H", "E", "12", "10", "60", "80", "11", "H", "H"))
Run Code Online (Sandbox Code Playgroud)

除了查看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
Run Code Online (Sandbox Code Playgroud)

事实上,因子是一个具有“级别”的整数向量:对应于每个唯一整数值​​的字符向量。幸运的是,您可以使用以下.attr()成员函数从 C++ 获取此信息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" 
Run Code Online (Sandbox Code Playgroud)

所以,要得到你想要的,你必须做三件事:

  1. 将返回类型从IntegerVectorto更改为CharacterVector(尽管您完全正确地认为输入应该是IntegerVector
  2. 使用获取因子的水平 CharacterVector levs = x.attr("levels");
  3. 比较levs[x[i]-1]"H"等,而不是x[i]--x[i]将始终是一个整数,给出它对应的水平向量的元素。我们这样做是-1因为 C++ 是 0-indexed 而 R 是 1-indexed。

其他注意事项:

正如您所说,很明显,“[您] 正在尝试学习如何在 R 中使用 Rcpp()。” 您肯定会想花一些时间使用资源,例如Rcpp for Everyone(这是关于因素的章节)、Rcpp 画廊(此特定链接是关于因素的文章)、Hadley 的 Rcpp 章节,以及此处提供的 Rcpp 小插曲.