我有两个带有时间戳的数据帧(格式为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
我已经检查了如何比较时间戳和计算时差,以及如何根据条件更改值... 但是我找不到任何东西可以选择“小于但最接近”的时间戳,也无法弄清楚如何应用所有这些逻辑。
任何帮助将不胜感激!
答案 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_ID0
和ID
。计算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