【问题标题】:R How to get the difference between current and next row that matches certain condition?R如何获得匹配特定条件的当前行和下一行之间的差异?
【发布时间】:2017-07-29 03:11:09
【问题描述】:

我知道这个问题似乎有点令人困惑。一个例子可能是,

                          Time        x
    2017-07-24 12:33:13.000000      0.0
    2017-07-24 12:33:14.000000      0.0
    2017-07-24 12:33:15.000000      0.0
    2017-07-24 12:33:16.000000      0.0
    2017-07-24 12:33:16.500000      1.0
    2017-07-24 12:33:17.000000      0.0
    2017-07-24 12:33:17.500000      0.0
    2017-07-24 12:33:18.500000      1.0

在 R 中,我希望有另一列,对于每一行,计算当前行的时间与 x 不为 0 的下一行的时间之间的差异。所以结果如下所示:

                          Time        x     diff
    2017-07-24 12:33:13.000000      0.0      3.5
    2017-07-24 12:33:14.000000      0.0      2.5
    2017-07-24 12:33:15.000000      0.0      1.5
    2017-07-24 12:33:16.000000      0.0      0.5
    2017-07-24 12:33:16.500000      1.0      0.0
    2017-07-24 12:33:17.000000      0.0      1.5
    2017-07-24 12:33:17.500000      0.0      1.0
    2017-07-24 12:33:18.500000      1.0      0.0

感谢您提前回答。

【问题讨论】:

    标签: r


    【解决方案1】:

    我认为 data.table() 库中的 Rolling join 可以提供帮助。

    这是我的解决方案:

    首先,让我们设置您的示例数据

    library('data.table')
    
    time <- as.POSIXct(c('2017-07-24 12:33:13.000000', '2017-07-24 12:33:14.000000', '2017-07-24 12:33:15.000000', '2017-07-24 12:33:16.000000', '2017-07-24 12:33:16.500000', '2017-07-24 12:33:17.000000', '2017-07-24 12:33:17.500000', '2017-07-24 12:33:18.500000'))
    
    x <- c(0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0)
    
    dat <- data.table(time, x)
    

    现在,让我们为连接添加一个虚拟列:

    dat[, key := 1]
    

    将数据子集到仅 x = 1 列到新表中

    ones <- dat[x==1, list(time, key, ref.time = time)]
    

    请注意,我还创建了一个 ref.time 列。那是为了执行减法。

    为滚动连接设置键

    setkey(dat, key, time)
    setkey(ones, key, time)
    

    现在进行连接。这回答了“与原始数据中任何给定行最近的 x==1 行是什么”的问题

    joined.dat <- ones[dat, roll = -Inf]
    

    计算您寻求的差异

    joined.dat[, diff := ref.time - time]
    

    最终输出:

                      time key            ref.time x     diff
    1: 2017-07-24 12:33:13   1 2017-07-24 12:33:16 0 3.5 secs
    2: 2017-07-24 12:33:14   1 2017-07-24 12:33:16 0 2.5 secs
    3: 2017-07-24 12:33:15   1 2017-07-24 12:33:16 0 1.5 secs
    4: 2017-07-24 12:33:16   1 2017-07-24 12:33:16 0 0.5 secs
    5: 2017-07-24 12:33:16   1 2017-07-24 12:33:16 1 0.0 secs
    6: 2017-07-24 12:33:17   1 2017-07-24 12:33:18 0 1.5 secs
    7: 2017-07-24 12:33:17   1 2017-07-24 12:33:18 0 1.0 secs
    8: 2017-07-24 12:33:18   1 2017-07-24 12:33:18 1 0.0 secs
    

    【讨论】:

    • 如果您使用dplyrtidyverse 或更有效地使用data.table,您的答案可能会更清晰。但我喜欢这个主意。干杯。 +1
    • 感谢您的支持和反馈!关于 data.table 的使用如何更有效,有什么具体的内容吗?当我把它放在一起时确实感觉有点麻烦,但我不确定如何简化它。
    【解决方案2】:

    查找“x == 1”所在的行:

    wh = which(dat$x == 1)
    

    我们可以构建一个最近(前向)“1”的索引向量:

    i = rep(wh, c(wh[1], diff(wh)))
    

    然后减去各自的“时间”:

    dat$Time[i] - dat$Time
    #Time differences in secs
    #[1] 3.5 2.5 1.5 0.5 0.0 1.5 1.0 0.0
    

    “数据”是:

    dat = structure(list(Time = structure(c(1500888793, 1500888794, 1500888795, 
    1500888796, 1500888796.5, 1500888797, 1500888797.5, 1500888798.5
    ), class = c("POSIXct", "POSIXt"), tzone = ""), x = c(0, 0, 0, 
    0, 1, 0, 0, 1)), .Names = c("Time", "x"), row.names = c(NA, 8L
    ), class = "data.frame")
    

    【讨论】:

      【解决方案3】:

      使用 Base R 和矢量化:

      a <- c(1, 3, 6, 10, 15, 17, 20, 23, 34)
      b <- c(0, 0, 0, 1,  0,  1,  0,  0,  1)
      

      手工,答案应该是这样的:

      c <- c(9, 7, 4, 0, 2, 0, 14, 11, 0)
      

      创建一个向量,其中 b 中的值是“枢轴”。我们也附上0作为起点:

      pivots <- c(0, which(b != 0))
      

      最后,在值0 和下一个1 之间多次重复这些枢轴。

      vec <- rep(a[pivots], times = diff(pivots)
      identical(c, vec - a)
      

      如果你想把它变成一个接受 values 向量/列和 pivots 向量/列的函数,你可以这样做:

      diffToNextPivot <- function(values, pivots) {
        pivots <- c(0, which(pivots != 0))
        vec <- rep(values[pivots], times = diff(pivots))
        vec - values
      }
      
      myDataFrame$diff <- diffToNextPivot(myDataFrame$Time, myDataFrame$x)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-10
        • 1970-01-01
        • 2022-01-16
        • 2017-05-31
        • 1970-01-01
        • 1970-01-01
        • 2011-09-24
        • 1970-01-01
        相关资源
        最近更新 更多