代码之家  ›  专栏  ›  技术社区  ›  Phi89

在rcpp函数中使用bool向量进行子集设置(rcpp初学者的问题…)

  •  0
  • Phi89  · 技术社区  · 6 年前

    问题描述(考虑成人和儿童不同价格的会员资格): 我有两个数据集,一个包含年龄和一个代码。第二个数据帧将这些代码“解码”为依赖于某个孩子或成年人的数值。我知道要匹配两个数据集中的代码并接收一个向量,该向量包含数据集中每个客户的数值。

    我可以使用标准的r功能来实现这一点,但是由于我的原始数据包含数百万个观测值,所以我希望使用rcpp包加快计算速度。

    不幸的是,我没有成功,特别是如何执行基于逻辑向量的子设置,就像我在R中所做的那样。我对Rcpp很陌生,对C++没有经验,所以我可能缺少一些非常基本的点。

    我附上了一个最低限度的工作实例为R和感谢任何帮助或解释!


    library(Rcpp)
    
    raw_data = data.frame(
           age = c(10, 14, 99, 67, 87, 54, 12, 44, 22, 8),
           iCode = c("code1", "code2", "code3", "code1", "code4", "code3", "code2", "code5", "code5", "code3"))
    
    decoder = data.frame(
            code = c("code1","code2","code3","code4","code5"),
            kid = c(0,0,0,0,100),
            adult = c(100,200,300,400,500))
    
    #-------- R approach (works, but takes ages for my original data set)
    calc_value = function(data, decoder){
    y = nrow(data)
    for (i in 1:nrow(data)){
       position_in_decoder = (data$iCode[i] == decoder$code)
       if (data$age[i] > 18){
              y[i] = decoder$adult[position_in_decoder]
          }else{
              y[i] = decoder$kid[position_in_decoder]
          }
        }
     return(y)
     }
    
    y = calc_value(raw_data, decoder)
    
    #--------- RCPP approach (I cannot make this one work) :(
    
    cppFunction(
    'NumericVector calc_Rcpp(DataFrame df, DataFrame decoder) {
     NumericVector age = df["age"];
     CharacterVector iCode = df["iCode"];
     CharacterVector code = decoder["code"];
     NumericVector adult = decoder["adult"];
     NumericVector kid = decoder["kid"];
     const int n = age.size();
     LogicalVector position;
     NumericVector y(n);
    
      for (int i=0; i < n; ++i) {
        position = (iCode[i] == code);
        if (age[i] > 18 ) y[i] = adult[position];
        else y[i] = kid[position];
        }
      return y;
      }')
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Ralf Stubner    6 年前

    这里没有必要去C++。正确使用r:

    raw_data = data.frame(
      age = c(10, 14, 99, 67, 87, 54, 12, 44, 22, 8),
      iCode = c("code1", "code2", "code3", "code1", "code4", "code3", "code2", "code5", "code5", "code3"))
    
    decoder = data.frame(
      code = c("code1","code2","code3","code4","code5"),
      kid = c(0,0,0,0,100),
      adult = c(100,200,300,400,500))
    
    foo <- merge(raw_data, decoder, by.x = "iCode", by.y = "code")
    foo$res <- ifelse(foo$age > 18, foo$adult, foo$kid)
    foo
    #>    iCode age kid adult res
    #> 1  code1  10   0   100   0
    #> 2  code1  67   0   100 100
    #> 3  code2  14   0   200   0
    #> 4  code2  12   0   200   0
    #> 5  code3  54   0   300 300
    #> 6  code3  99   0   300 300
    #> 7  code3   8   0   300   0
    #> 8  code4  87   0   400 400
    #> 9  code5  44 100   500 500
    #> 10 code5  22 100   500 500
    

    这也适用于大型数据集。