根据条件查找列中最接近的时间戳记

时间:2019-07-31 14:01:56

标签: r dataframe data.table

我在R中有一个数据框,它与此相似:

time                value
13-07-2019 02:34:28 9.07
13-07-2019 02:34:57 8.87
13-07-2019 02:35:27 9.34
13-07-2019 02:46:08 X
13-07-2019 02:46:38 4.5
13-07-2019 02:47:08 6.66
13-07-2019 02:47:37 8.7
13-07-2019 02:48:08 4.7
13-07-2019 02:48:39 X
13-07-2019 02:49:08 7.8
13-07-2019 02:49:39 9.8
13-07-2019 02:50:38 X
13-07-2019 02:51:08 2.34
13-07-2019 02:51:39 5.67
13-07-2019 02:52:08 X
13-07-2019 02:52:38 8.766
13-07-2019 02:53:08 5.456
13-07-2019 02:53:38 X
13-07-2019 02:54:08 6.544
13-07-2019 02:54:39 9.877
13-07-2019 02:55:08 X

我想要的是找出x时的最近时间。例如:

13-07-2019 02:35:27 9.34
13-07-2019 02:46:08 X
13-07-2019 02:46:38 4.5

这里X的最近时间是13-07-2019 02:46:38

13-07-2019 02:53:08 5.456
13-07-2019 02:53:38 X
13-07-2019 02:54:08 6.544

这里是13-07-2019 02:53:08

我只需要考虑30秒以内的时间。如果超过30秒,我会认为时间是之前的30秒

13-07-2019 01:53:08 5.456
13-07-2019 02:53:38 X
13-07-2019 04:54:08 6.544

在这里,我需要将时间限制为:13-07-2019 02:53:08,这是较低的30秒,因为它的差值超过30秒。

最后,我需要获取一个具有n个值的数据框,其中n是我在数据框值列中拥有x的次数

2 个答案:

答案 0 :(得分:2)

由于您用data.table标记了问题, 这是一个假设您有一个选择 (此处命名为dt) 和你的时间是弦 (如果已经POSIXct,请跳过第一行):

dt[, time := as.POSIXct(time, format = "%d-%m-%Y %H:%M:%S")]

max_difftime <- as.difftime(30L, units = "mins")
lambda <- function(rolled_time, x_time) {
    invalid <- abs(rolled_time - x_time) > max_difftime
    if (any(invalid)) {
        rolled_time[invalid] <- x_time[invalid] - max_difftime
    }
    rolled_time
}

dt[value != "X"
   ][dt[value == "X"],
     .(x_time = i.time, time = lambda(x.time, i.time)),
     on = "time",
     roll = "nearest"]
                x_time                time
1: 2019-07-13 02:46:08 2019-07-13 02:46:38
2: 2019-07-13 02:48:39 2019-07-13 02:49:08
3: 2019-07-13 02:50:38 2019-07-13 02:51:08
4: 2019-07-13 02:52:08 2019-07-13 02:51:39
5: 2019-07-13 02:53:38 2019-07-13 02:53:08
6: 2019-07-13 03:24:40 2019-07-13 02:54:40

我对示例数据进行了一些修改,以使最后一行具有03:24:40

代码在valueX的行与其余行之间执行滚动连接, 寻找最近的timelambda函数比较找到的最近时间 (由x.time公开为data.table) 与找到X的时间 (由i.time公开为data.table), 并调整时差大于30分钟的值。 我添加了x_time列只是为了显示比较, 您可以在不需要时删除它。

答案 1 :(得分:0)

如果您只是在+ -30秒内计算没有非NA值的X数,则可以

1)使用非等额联接:

DT[!is.na(value)][
    DT[is.na(value), .(now=time, start=time-30, end=time+30)], 
    on=.(time>=start, time<=end), .(time=now, .N>0), by=.EACHI][, 
        sum(V2)]

2)使用between

start <- DT2[!is.na(value), time-30]
end <- DT2[!is.na(value), time+30]
DT2[is.na(value), sum(sapply(time, function(x) !any(between(x, start, end))))]

数据:

library(data.table)
DT <- fread("time,value
13-07-2019 02:34:28,9.07
13-07-2019 02:34:57,8.87
13-07-2019 02:35:27,9.34
13-07-2019 02:46:08,NA
13-07-2019 02:46:38,4.5
13-07-2019 02:47:08,6.66
13-07-2019 02:47:37,8.7
13-07-2019 02:48:08,4.7
13-07-2019 02:48:39,NA
13-07-2019 02:49:08,7.8
13-07-2019 02:49:39,9.8
13-07-2019 02:50:38,NA
13-07-2019 02:51:08,2.34
13-07-2019 02:51:39,5.67
13-07-2019 02:52:08,NA
13-07-2019 02:52:38,8.766
13-07-2019 02:53:08,5.456
13-07-2019 02:53:38,NA
13-07-2019 02:54:08,6.544
13-07-2019 02:54:39,9.877
13-07-2019 02:55:08,NA
14-07-2019 01:53:08,5.456
14-07-2019 02:53:38,NA
14-07-2019 04:54:08,6.544")
DT[, time := as.POSIXct(time, format = "%d-%m-%Y %H:%M:%S")]
DT2 <- copy(DT)