按行迭代导入的数据帧中的向量

时间:2019-01-07 18:51:11

标签: r rcpp

我正在尝试从R转换为c ++编码。如果您选择不赞成这个问题,至少请给我一个答案,以使我学到一些东西。我的问题是,一旦我将数据传递给c ++,我应该如何在c ++中进行逐行计算?从概念上讲,我了解到,一旦我通过c ++一个数据帧,c ++就会将每一列视为自己必须明确命名的向量。我遇到麻烦的地方是设置一个for循环,一次遍历所有向量的相同位置,从而在功能上模拟R中的逐行函数。我也想将此问题扩展到以下应用程序:

  1. 如何设置循环遍历行并返回向量的循环。像R中的rowum?在高级R中有一个使用矩阵的例子,但是命名法不能转换为数据帧中的向量。
  2. 我将如何设置循环遍历一行并更改每一行中的值并返回修改后的向量的循环?
  3. 如何设置一个循环遍历行范围的循环,从而实现滑动窗口功能?像这样:

    ## an example of a for loop in R that I want to recapitulate in c++
    output <- list() 
    
    for(i in 1:nrow(df)){
      end_row <- i+3
      df_tmp <- df[i:end_row, ]
      ## do some function here
      output[[i]] <- list(df_tmp)
    }
    
  4. 如何在问题3中设置相同的滚动函数,但是以允许我有条件地扩展矢量长度的方式?在R中,我编写了使用apply的函数,该函数在一定范围的行上进行迭代,然后返回新数据帧的列表,然后将其转换为大数据帧。从概念上讲,一次对这个向量进行一次处理现在对我来说很困惑。

让我们说我在R中有这个数据框

#example data    
a <- c(0, 2, 4, 6, 8, 10)
b <- c(1, 3, 5, 7, 9, 11)
c <- c("chr1", "chr1", "chr1", "chr1", "chr1", "chr1")
d <- c(10.2, 10.2, 4.3, 4.3, 3.4, 7.9)
e <- c("a", "t", "t", "g", "c", "a")

df <- data.frame(a, b, c, d, e)

在c ++中,我已经走了这么远:

#include <algorithm>
#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
DataFrame modifyDataFrame(DataFrame df) {

  // access the columns
  IntegerVector a = df["a"];
  IntegerVector b = df["b"];
  CharacterVector c = df["c"];
  IntegerVector d = df["d"];
  CharacterVector e = df["e"];

// write the for loop. I'm attempting to define a single
//position and then apply it to all vectors... 
//but no versions of this approach have worked.   

  for(int i=0; i < a.length(); ++i){

  // do some function
  }
  // return a new data frame
  return DataFrame::create(_["a"]= a, _["b"]= b, _["c"]= c, _["d"]= d, _["e"]=e);
}

我一直在关注“高级R”部分。我努力掌握的部分是多向量四循环构造以及如何定义范围迭代器。根据我的代码,这也是您的解释吗?我是否需要为每个向量创建一个迭代器,还是可以仅根据一个向量的长度定义一个位置,然后将其应用于所有向量?

对我来说,最简单的方法就是看一个例子。一旦看到了功能代码的示例,就可以应用我一直在阅读的概念。

编辑:是否可以在RCPP文档中添加类似的示例?我想象很多人在这一步都在挣扎。考虑到数据框是最常见的r数据容器之一,我认为将通过另外两个数据框示例来大大增强rcpp文档-乍一看,概念上的转换并不容易。

1 个答案:

答案 0 :(得分:2)

我不认为从这里使用C ++可以提高性能。但是,如果您有一组长度相等的向量(data.frame保证),则可以简单地使用一个索引进行迭代:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
DataFrame modifyDataFrame(DataFrame df) {

  // access the columns
  IntegerVector a = df["a"];
  IntegerVector b = df["b"];
  CharacterVector c = df["c"];
  NumericVector d = df["d"];
  CharacterVector e = df["e"];

  for(int i=0; i < df.nrow(); ++i){
    a(i) += 1;
    b(i) += 2;
    c(i) += "c";
    d(i) += 3;
    e(i) += "e";
  }
  // return a new data frame
  return DataFrame::create(_["a"]= a, _["b"]= b, _["c"]= c, _["d"]= d, _["e"]=e);
}
/*** R
a <- c(0, 2, 4, 6, 8, 10)
b <- c(1, 3, 5, 7, 9, 11)
c <- c("chr1", "chr1", "chr1", "chr1", "chr1", "chr1")
d <- c(10.2, 10.2, 4.3, 4.3, 3.4, 7.9)
e <- c("a", "t", "t", "g", "c", "a")

df <- data.frame(a, b, c, d, e)
modifyDataFrame(df)  
*/

结果:

> modifyDataFrame(df)  
   a  b     c    d  e
1  1  3 chr1c 13.2 ae
2  3  5 chr1c 13.2 te
3  5  7 chr1c  7.3 te
4  7  9 chr1c  7.3 ge
5  9 11 chr1c  6.4 ce
6 11 13 chr1c 10.9 ae

在这里,我使用的是nrow()类的DataFrame方法,参见the Rcpp API。就像length()方法一样,它使用R的C API。我只是发现使用DataFrame方法比选择其中一个向量来检索长度更合乎逻辑。结果将是相同的。

对于滑动窗口,我将首先研究RcppRoll包。