R如何获得符合特定条件的当前行与下一行之间的差异?

时间:2017-07-28 18:35:54

标签: r

我明白这个问题似乎有些令人困惑。一个例子可能是,

                          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

感谢您提前回答。

3 个答案:

答案 0 :(得分:3)

我认为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)

现在进行加入。这回答了问题&#34;原始数据中任何给定行的最近x == 1行是什么&#34;

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

答案 1 :(得分: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”是:

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")

答案 2 :(得分:0)

使用Base R和vectorization:

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中的值是'pivotots'。我们还附加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)