基于使用列的累积和创建的分组筛选R data.table

基于使用列的累积和创建的分组筛选R data.table,r,filter,data.table,cumsum,R,Filter,Data.table,Cumsum,我需要一个高效的data.table解决方案来过滤一列的累积和中的每300个的第一个和最后一个实例。我真正的数据集是数百万行,所以我不是在寻找循环解决方案 #Example data: dt <- data.table(idcolref=c(1:1000),y=rep(10,1000)) #示例数据: dt我想我已经正确地解释了您的要求: 要计算向量(列)的累积和 如果累计总和达到300,您希望将其重置回0 每次重置为0时,您都希望表示向量的这些值在一个新组中 您希望选择每个组的第一

我需要一个高效的data.table解决方案来过滤一列的累积和中的每300个的第一个和最后一个实例。我真正的数据集是数百万行,所以我不是在寻找循环解决方案

#Example data:
  dt <- data.table(idcolref=c(1:1000),y=rep(10,1000))
#示例数据:

dt我想我已经正确地解释了您的要求:

  • 要计算向量(列)的累积和
  • 如果累计总和达到300,您希望将其重置回0
  • 每次重置为0时,您都希望表示向量的这些值在一个新组中
  • 您希望选择每个组的第一行和最后一行
  • 如果是这种情况,您可以在
    Rcpp

    library(data.table)
    
    dt <- data.table(x=rep(5,1e7),y=rep(10,1e7))
    ## adding a row index to keep track of which rows are returned
    dt[, id := .I]
    
    library(Rcpp)
    
    cppFunction('Rcpp::NumericVector findGroupRows(Rcpp::NumericVector x) {
    
      int cumsum = 0;
      int grpCounter = 0;
      size_t n = x.length();
      Rcpp::NumericVector groupedCumSum(n);
    
      for ( size_t i = 0; i < n; i++) {
        cumsum += x[i];
        if (cumsum > 300) {
          cumsum = 0;
          grpCounter++;
        }
        groupedCumSum[i] = grpCounter;
      }
      return groupedCumSum;
    }')
    
    dt[, grp := findGroupRows(y)]
    
    dt[ dt[, .I[c(1, .N)], by = grp]$V1]
    
    库(data.table)
    
    dt我想我已经正确地解释了您的要求:

  • 要计算向量(列)的累积和
  • 如果累计总和达到300,您希望将其重置回0
  • 每次重置为0时,您都希望表示向量的这些值在一个新组中
  • 您希望选择每个组的第一行和最后一行
  • 如果是这种情况,您可以在
    Rcpp

    library(data.table)
    
    dt <- data.table(x=rep(5,1e7),y=rep(10,1e7))
    ## adding a row index to keep track of which rows are returned
    dt[, id := .I]
    
    library(Rcpp)
    
    cppFunction('Rcpp::NumericVector findGroupRows(Rcpp::NumericVector x) {
    
      int cumsum = 0;
      int grpCounter = 0;
      size_t n = x.length();
      Rcpp::NumericVector groupedCumSum(n);
    
      for ( size_t i = 0; i < n; i++) {
        cumsum += x[i];
        if (cumsum > 300) {
          cumsum = 0;
          grpCounter++;
        }
        groupedCumSum[i] = grpCounter;
      }
      return groupedCumSum;
    }')
    
    dt[, grp := findGroupRows(y)]
    
    dt[ dt[, .I[c(1, .N)], by = grp]$V1]
    
    库(data.table)
    
    dt仅使用
    数据的简单解决方案。表
    和基本R函数:

    dt[, grp2 := (cumsum(y) - 1) %/% 300]  
    
    # straight forward solution:
    dt[, .SD[c(1, .N)], by = "grp"]
    
    # more efficient for large datasets, as suggested by SymbolixAU
    dt[ dt[, .I[c(1, .N)], by = "grp"]$V1]
    
    # check if your groups are of the correct size
    table(dt[, .N[[1]], by = "grp"]$V1)
    
    • %/%
      是整数除法运算符
    • .SD
      是按组划分的
      数据表的当前子集
    • .N
      是当前行中的行数 子集(与
      nrow(.SD
      )相同)
    • -1
      确保第一组的大小正确

    仅使用
    数据的简单解决方案。表
    和基本R函数:

    dt[, grp2 := (cumsum(y) - 1) %/% 300]  
    
    # straight forward solution:
    dt[, .SD[c(1, .N)], by = "grp"]
    
    # more efficient for large datasets, as suggested by SymbolixAU
    dt[ dt[, .I[c(1, .N)], by = "grp"]$V1]
    
    # check if your groups are of the correct size
    table(dt[, .N[[1]], by = "grp"]$V1)
    
    • %/%
      是整数除法运算符
    • .SD
      是按组划分的
      数据表的当前子集
    • .N
      是当前行中的行数 子集(与
      nrow(.SD
      )相同)
    • -1
      确保第一组的大小正确

    x是您的组?不,我需要根据x(或y)生成组。您能更清楚地说,哪一列是您的id列吗?您确定您的
    dt.所需的
    正确吗?如果在
    dt[,id:=.I]
    上放置索引列,则表明第一组是第1行和第122行?为什么输出的第一个值为0?应该是10吗?x是您的组吗?不,我需要根据x(或y)生成组。您能更清楚一点,哪一列是您的id列吗?您确定您的
    dt.所需的
    正确吗?如果在
    dt[,id:=.I]
    上放置索引列,则表明第一组是第1行和第122行?为什么输出的第一个值为0?是不是应该是10?那是相当整洁的。尽管cpp的速度惊人地快(31人而不是30人),但您的团队只差一个元素。很好。@StefanF-你确定我只差一个元素吗?@NealBarsch-是的。值得记住的是,“矢量化”几乎是用编译语言编写的循环,通常是
    C
    C++
    fortran
    尝试
    表(dt[,.N[[1]],by=“grp”]$V1)
    ,至少在我的机器上,它给我的大小是错误的(第一组是30个元素,后面一组是31个)。在编辑我的原始解决方案之前,我遇到了与之相反的问题(例如,我的第一组解决方案太小了)。这
    dt[dt[,.I[c(1,N)],by=grp2]$V1]
    非常简洁。尽管cpp的速度惊人地快(31人而不是30人),但您的团队只差一个元素。很好。@StefanF-你确定我只差一个元素吗?@NealBarsch-是的。值得记住的是,“矢量化”几乎是用编译语言编写的循环,通常是
    C
    C++
    fortran
    尝试
    表(dt[,.N[[1]],by=“grp”]$V1)
    ,至少在我的机器上,它给我的大小是错误的(第一组是30个元素,后面一组是31个)。在编辑原始解决方案之前,我遇到了与之相反的问题(例如,我的第一个组太小)。