通过id产生与Rcpp相关的data.frame并且与请求类型不兼容'

时间:2016-04-14 15:10:32

标签: r dataframe rcpp

我的Rcpp功能有问题。我基本上有一个数据框(尺寸N*K)和一个数字向量(尺寸H < N)作为输入,作为输出我想要返回一个数据框(尺寸H * M )具有相同的整数向量的行索引。

数据框:

val1 val2 val3 val4
1   0.2059  A   14
2   0.5700  B   61
3   0.5354  C   24
4   0.8123  D   78
5   0.7542  E   39
6   0.6433  F   17
7   0.2452  G   96
8   0.2557  H   93
9   0.7208  I   36
10  0.2565  L   12

INTEGER VECTOR:

2
4
7
10 

输出:

2   0.5700  B   61
4   0.8123  D   78
7   0.2452  G   96
10  0.2565  L   12

这是我的代码。在此先感谢您的帮助:

#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::export]]
DataFrame matchRows(DataFrame &OriginalDF, NumericVector &ReducedVector)
{
  int nr1 = OriginalDF.nrows(), nc1= OriginalDF.size();
  int nr2 = ReducedVector.size();

  if (nr1 < nr2) throw std::range_error("Size of data frame has to be higher     than the target random subset!");

  std::map<double, DataFrame> X;
  for (int j = 0; j < nr2; j++)
  {
    NumericVector tmp1=wrap(OriginalDF[ReducedVector[j]]);
    tmp1.attr("dim")=Dimension(int(tmp1.size())/nc1,nc1);

    DataFrame NewDF(wrap(tmp1));
    NewDF.push_back(OriginalDF[ReducedVector[j]]);
    NewDF.attr("names")=OriginalDF.attr("names");

    X[ReducedVector[j]] = NewDF;
  }
  return wrap(X);
}

我的代码的先前版本不幸导致RStudio崩溃。理想情况下,有一些方法可以将数据框初始化为零,然后使用push_back()累加值:

// [[Rcpp::export]]
DataFrame matchRows(DataFrame &OriginalDF, NumericVector &ReducedVector)
{
  int nr1 = OriginalDF.nrows(), nc1 = OriginalDF.size();
  int nr2 = ReducedVector.size();

  if (nr1 < nr2) throw std::range_error("Size of data frame has to be higher than the target random subset!");

  DataFrame NewDF;
  for (int j = 0; j < nr2; j++)
  {
    NewDF.push_back(OriginalDF[ReducedVector[j]]);
  }
  return NewDF;
}

1 个答案:

答案 0 :(得分:2)

好的,所以你在这里真正要做的只是在Rcpp中按行ID的data.frame子集。

e.g。

D[c(2,4,7,10),]

首先,在您的代码中定义:

std::map<double, DataFrame> X;

没有wrap()转换来处理此类型的对象。此外,在这种情况下真的不应该使用wrap,因为它是由函数指定的返回类型自动转换的。

要有效地对data.frame进行子集化,请不要使用.push_back()功能,因为它始终需要完整副本,因此效率不高。

相反,您希望使用idx变量和Rcpp vector subsetting,如下所示:

#include <Rcpp.h>

// Extract rows from data.frame object in Rcpp
// [[Rcpp::export]]
Rcpp::DataFrame matchRows(Rcpp::DataFrame D, Rcpp::IntegerVector idx) {

  // First, break apart each vector
  Rcpp::IntegerVector   val1 = D["val1"];
  Rcpp::NumericVector   val2 = D["val2"];
  Rcpp::CharacterVector val3 = D["val3"];
  Rcpp::NumericVector   val4 = D["val4"];

  // We assume that the index passed in starts at 1. 
  // Hence, we need to adjust the idx to start at 0 with:
  idx = idx - 1;

  // Next up, create a new DataFrame Object with selected rows subset. 
  return Rcpp::DataFrame::create(Rcpp::Named("val1")  = val1[idx],
                                 Rcpp::Named("val2")  = val2[idx],
                                 Rcpp::Named("val3")  = val3[idx],
                                 Rcpp::Named("val3")  = val4[idx]
                                 );
}

/*** R
# Make some data
set.seed(1337)
D = data.frame(val1 = 1:10, 
               val2 = rnorm(10), 
               val3 = letters[1:10], 
               val4 = sample(1:100, 10),
               stringsAsFactor=FALSE)

# Create index that starts at 1 instead of 0. 
# This will be converted in the C++ function.
idx = c(2,4,7,10) 

matchRows(D, idx)

*/

详细信息中的恶魔是我们将索引减1,以便在调用索引之前考虑从0开始对R&#39; 1开始的C ++索引。这也可以在C ++代码中处理。但是,我会将其作为一种练习。