【问题标题】:R data.table count rows until value is reachedR data.table 计数行直到达到值
【发布时间】:2016-02-27 13:33:30
【问题描述】:

我想在 data.table 中返回一个新列,该列显示在达到低于当前值(Temp)之前的行数。

library(data.table)
set.seed(123)
DT <- data.table( Temp = runif(10,0,20) )

这就是我想要的样子:

set.seed(123)
DT <- data.table(
        Temp = runif(10,0,20),
        Day_Below_Temp = c("5","1","3","2","1","NA","3","1","1","NA")
)

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    使用当前开发版本中新实现的非 equi 连接,可以通过如下简单的方式完成:

    require(data.table) # v1.9.7+
    DT[, row := .I] # add row numbers
    DT[DT, x.row-i.row, on = .(row > row, Temp < Temp), mult="first"]
    # [1]  5  1  3  2  1 NA  3  1  1 NA
    

    行号是必需的,因为我们需要找到低于当前索引的索引,因此需要成为连接中的条件。我们执行 self-join,即对于DT(内部)中的每一行,根据提供给on 参数的条件,我们在DT(外部)中找到第一个匹配的行索引)。然后我们减去行索引以获得当前行的位置。 x.row 指外层DTi.row 到内层DT 的索引。

    要获取开发版,请参阅安装说明here


    在 1e5 行上:

    set.seed(123)
    DT <- data.table(Temp = runif(1e5L, 0L, 20L))
    
    DT[, row := .I]
    system.time({
        ans = DT[DT, x.row-i.row, on = .(row > row, Temp < Temp), mult="first", verbose=TRUE]
    })
    # Non-equi join operators detected ... 
    #   forder took ... 0.001 secs
    #   Generating non-equi group ids ... done in 0.452 secs
    #   Recomputing forder with non-equi ids ... done in 0.001 secs
    #   Found 623 non-equi group(s) ...
    # Starting bmerge ...done in 8.118 secs
    # Detected that j uses these columns: x.row,i.row 
    #    user  system elapsed 
    #   8.492   0.038   8.577 
    
    head(ans)
    # [1]  5  1  3  2  1 12
    tail(ans)
    # [1]  2  1  1  2  1 NA
    

    【讨论】:

      【解决方案2】:

      这是一个dplyr 方法:

      library(dplyr)
      set.seed(123)
      dt <- data.frame( Temp = runif(10,0,20) )
      dt %>% mutate(Day_Below_Temp = 
                       sapply(1:length(Temp), function(x) min(which(.$Temp[x:length(.$Temp)] < .$Temp[x]))-1))
      
              Temp Day_Below_Temp
      1   5.751550              5
      2  15.766103              1
      3   8.179538              3
      4  17.660348              2
      5  18.809346              1
      6   0.911130            Inf
      7  10.562110              3
      8  17.848381              1
      9  11.028700              1
      10  9.132295            Inf
      

      【讨论】:

      • 好的,这很好@jeremycg,如果我想检查 Temp 值低于替代列(附加列)值的哪一行,为了确保我理解正确,这种方法将如何改变?谢谢
      • 不幸的是,这(以及我自己删除的答案)似乎像潮湿的一周一样缓慢。即使在 100K 的情况下,这也需要一分钟的时间。我认为必须有一种方法可以通过一些连接或一些棘手的事情来解决这个问题。阿伦,你在哪里?!
      • 我想知道这里的dplyr 角色是什么? mutate?这不能仅通过$ 来实现吗?
      • :) 别担心,我会活下去
      • @thelatemail,哈哈.. 刚刚看到这条评论。目前我想不出比(新实现的)非 equi 连接更快的方法。在 100K 行上需要大约 8.5 秒。
      【解决方案3】:

      这可以完成工作 - 虽然不是很快

      DT[, rowN := .I]
      
      DT[, Day_Below_Temp := which(DT$Temp[rowN:nrow(DT)] < Temp)[1] - 1, 
         by = rowN
         ][, rowN := NULL]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-03
        • 1970-01-01
        • 2020-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多