计算按变量分组的两个日期之间的差异

时间:2019-05-01 10:54:15

标签: r tidyverse

我正在寻找一些帮助编写更有效的代码。 我有以下数据集。

Report| ReportPeriod|ObsDate
1     |     15      |2017-12-31 00:00:00
1     |     15      |2017-12-31 06:00:00
1     |     15      |2017-12-31 12:30:00
2     |     11      |2018-01-01 07:00:00
2     |     11      |2018-01-01 13:00:00
2     |     11      |2018-01-01 16:30:00

第一列是“报告”,它是特定报告的唯一标识符。 在数据集中,只有两个报告(1和2)。 第二列是“ ReportPeriod”,它与特定报告相同。报告1为15小时,报告2为11小时。 第三列“ ObsDate”是特定报告中的不同观察结果。

问题:我需要找出按“报告”分组的观察之间的时间差。我使用以下代码做到了这一点。

example<- data.frame(Report=c(1,1,1,2,2,2), ReportPeriod=c(15,15,15,11,11,11),
                     ObsDate=c(as.POSIXct("2017-12-31 00:00:00"), as.POSIXct("2017-12-31 06:00:00"),
                               as.POSIXct("2017-12-31 12:30:00"), as.POSIXct("2018-01-01 07:00:00"),
                               as.POSIXct("2018-01-01 13:00:00"), as.POSIXct("2018-01-01 16:30:00")))

example<- example %>% group_by(Report) %>% 
  mutate(DiffPeriod= (ObsDate-lag(ObsDate)))

输出为:

Report| ReportPeriod|ObsDate            |DiffPeriod
1     |     15      |2017-12-31 00:00:00|NA
1     |     15      |2017-12-31 06:00:00|6.0
1     |     15      |2017-12-31 12:30:00|6.5
2     |     11      |2018-01-01 07:00:00|NA
2     |     11      |2018-01-01 13:00:00|6.0
2     |     11      |2018-01-01 16:30:00|3.5

现在“报告”的前两个条目为NA。这些值应该是DiffPeriod的总和减去报告期间“ ReportPeriod”的总和。

我使用以下代码做到了这一点。

xyz<- data.frame()
for (i in unique(example$Report)) {
  df<- example %>% filter(Report==i)
  hrs<- sum(df$DiffPeriod, na.rm = TRUE)
  tot<- df$ReportPeriod[1]
  bal<- tot-hrs
  df$DiffPeriod[1]<- bal
  xyz<- xyz %>% bind_rows(df)
}

最终输出是:

Report| ReportPeriod|ObsDate            |DiffPeriod
1     |     15      |2017-12-31 00:00:00|2.5
1     |     15      |2017-12-31 06:00:00|6.0
1     |     15      |2017-12-31 12:30:00|6.5
2     |     11      |2018-01-01 07:00:00|1.5
2     |     11      |2018-01-01 13:00:00|6.0
2     |     11      |2018-01-01 16:30:00|3.5

是否有更好/更有效的方法来完成我在tidyverse的for循环中所做的工作?

谢谢。

1 个答案:

答案 0 :(得分:2)

假设ReportPeriod总是在几个小时内,我们首先可以得到ObsDatelag(ObsDate)之间的差额,然后是replace NA,这仅仅是第一行通过对每个组(ReportPeriod)取sum的第一值与DiffPeriod的{​​{1}}之间的差。

Report