根据多个行和列中的多个条件比较时间戳

时间:2019-04-30 01:49:45

标签: r timestamp match

我有两个带有时间戳的数据帧(格式为as.POSIXct,格式为“%Y-%m-%d%H:%M:%S”)。

df_ID1
 ID         DATETIME               TIMEDIFF                 EV
  A         2019-03-26 06:13:00    2019-03-26 00:13:00      1
  B         2019-04-03 08:00:00    2019-04-03 02:00:00      1
  B         2019-04-04 12:35:00    2019-04-04 06:35:00      1

df_ID0
  ID         DATETIME                   
  A         2019-03-26 00:02:00         
  A         2019-03-26 04:55:00     
  A         2019-03-26 11:22:00
  B         2019-04-02 20:43:00
  B         2019-04-04 11:03:00
  B         2019-04-06 03:12:00

我想将df_ID1中的DATETIME与具有相同ID的df_ID0中的DATETIME进行比较,并且DATETIME是“小于但最接近” df_ID1中的DATETIME,

对于两个匹配的数据帧中的对,我想进一步比较df_ID1中的TIMEDIFF和df_ID0中匹配的DATETIME,如果df_ID1中的TIMEDIFF大于df_ID0中的DATETIME,则将df_ID1中的EV 1更改为4。

我想要的结果是

 df_ID1
 ID         DATETIME               TIMEDIFF                 EV
  A         2019-03-26 06:13:00    2019-03-26 00:13:00      1
  B         2019-04-03 08:00:00    2019-04-03 02:00:00      4
  B         2019-04-04 12:35:00    2019-04-04 06:35:00      1

我已经检查了如何比较时间戳和计算时差,以及如何根据条件更改值... 但是我找不到任何东西可以选择“小于但最接近”的时间戳,也无法弄清楚如何应用所有这些逻辑。

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:2)

您可以使用for循环来做到这一点,但要记住,如果您的实际数据库很大,那么开销将是非常糟糕的性能。

for(i in 1:nrow(df_1)){
  sub <- subset(df_0, ID == df_1$ID[i]) # filter on ID
  df_0_dt <- max(sub[sub$DATETIME < df_1$DATETIME[i],]$DATETIME) # Take max of those with DATETIME less than (ie less than but closest to)
  if(df_0_dt < df_1$TIMEDIFF[i]){ # final condition
    df_1[i, "EV"] <- 4
  } 
}
df_1
# A tibble: 3 x 4
  ID    DATETIME            TIMEDIFF               EV
  <chr> <dttm>              <dttm>              <dbl>
1 A     2019-03-26 06:13:00 2019-03-26 00:13:00     1
2 B     2019-04-03 08:00:00 2019-04-03 02:00:00     4
3 B     2019-04-04 12:35:00 2019-04-04 06:35:00     1

答案 1 :(得分:1)

使用嵌套mapply的一个选项是首先基于split df_ID1 df_ID0ID。计算df_ID1中的每个值与相同的df_ID0的{​​{1}}的时间差。获取索引“小于但最接近”,并将其存储在ID中,如果对应的inds列的值大于匹配的TIMEDIFF值,则将其值更改为4。 / p>

DATETIME

数据

df_ID1$EV[unlist(mapply(function(x, y) {
                   mapply(function(p, q) {
                     vals = as.numeric(difftime(p, y$DATETIME))
                     inds = which(vals == min(vals[vals > 0]))
                     q > y$DATETIME[inds]
                    }, x$DATETIME, x$TIMEDIFF)
                 }, split(df_ID1, df_ID1$ID), split(df_ID0, df_ID0$ID)))] <- 4


df_ID1
#  ID            DATETIME            TIMEDIFF EV
#1  A 2019-03-26 06:13:00 2019-03-26 00:13:00  1
#2  B 2019-04-03 08:00:00 2019-04-03 02:00:00  4
#3  B 2019-04-04 12:35:00 2019-04-04 06:35:00  1