如何以45分钟为间隔将日期和时间四舍五入为日期和时间

时间:2019-12-30 07:49:36

标签: r rounding lubridate posixct

我有一个数据框,其中包含一个名为DateTime的变量,其中包含有关日期和时间的数据。下面我显示一个示例:

df<- data.frame(DateTime=c("2016-08-23 00:22:23","2016-08-23 00:26:38","2016-08-23 01:04:12","2016-08-23 02:27:58","2016-08-23 03:04:31","2016-08-23 04:51:46"))
df$DateTime<- as.POSIXct(df$DateTime, format="%Y-%m-%d %H:%M:%S", tz="UTC")

df
             DateTime
1 2016-08-23 00:22:23
2 2016-08-23 00:26:38
3 2016-08-23 01:04:12
4 2016-08-23 02:27:58
5 2016-08-23 03:04:31
6 2016-08-23 04:51:46

我想创建一个名为DateTime45的变量,该变量以45分钟为间隔将日期和时间四舍五入。下面我展示了到目前为止我尝试过的:

df$DateTime45<- round_date(df$DateTime, "45 mins")

df

             DateTime          DateTime45
1 2016-08-23 00:22:23 2016-08-23 00:00:00
2 2016-08-23 00:26:38 2016-08-23 00:45:00
3 2016-08-23 01:04:12 2016-08-23 01:00:00
4 2016-08-23 02:27:58 2016-08-23 02:45:00
5 2016-08-23 03:04:31 2016-08-23 03:00:00
6 2016-08-23 04:51:46 2016-08-23 04:45:00

但是,如您所见,由于时间间隔不是均匀分布的,所以它会产生一些奇怪的现象。我想改成这个:

df
             DateTime          DateTime45
1 2016-08-23 00:22:23 2016-08-23 00:00:00
2 2016-08-23 00:26:38 2016-08-23 00:45:00
3 2016-08-23 01:04:12 2016-08-23 00:45:00
4 2016-08-23 02:27:58 2016-08-23 02:15:00
5 2016-08-23 03:04:31 2016-08-23 03:00:00
6 2016-08-23 04:51:46 2016-08-23 04:30:00

如果我们以24小时制考虑时间,则45个时间间隔的限制如下:

TimeIntervalLimits<- seq.POSIXt(as.POSIXct("2016-08-23 00:00:00"), as.POSIXct("2016-08-24 00:45:00"), by = "45 min", format="%Y-%m-%d %H-%M-%S", tz="UTC")
TimeIntervalLimits<- as.data.frame(TimeIntervalLimits)

TimeIntervalLimits

    TimeIntervalLimits
1  2016-08-23 00:00:00
2  2016-08-23 00:45:00
3  2016-08-23 01:30:00
4  2016-08-23 02:15:00
5  2016-08-23 03:00:00
6  2016-08-23 03:45:00
7  2016-08-23 04:30:00
8  2016-08-23 05:15:00
9  2016-08-23 06:00:00
10 2016-08-23 06:45:00
11 2016-08-23 07:30:00
12 2016-08-23 08:15:00
13 2016-08-23 09:00:00
14 2016-08-23 09:45:00
15 2016-08-23 10:30:00
16 2016-08-23 11:15:00
17 2016-08-23 12:00:00
18 2016-08-23 12:45:00
19 2016-08-23 13:30:00
20 2016-08-23 14:15:00
21 2016-08-23 15:00:00
22 2016-08-23 15:45:00
23 2016-08-23 16:30:00
24 2016-08-23 17:15:00
25 2016-08-23 18:00:00
26 2016-08-23 18:45:00
27 2016-08-23 19:30:00
28 2016-08-23 20:15:00
29 2016-08-23 21:00:00
30 2016-08-23 21:45:00
31 2016-08-23 22:30:00
32 2016-08-23 23:15:00
33 2016-08-24 00:00:00
 .      .         .
 .      .         .

有人知道如何以我想要的方式获取变量DateTime45吗?

预先感谢

1 个答案:

答案 0 :(得分:4)

编辑

我之前误解了这个问题。由于日期时间可以转换为数字,因此可以通过使用一些数学操作来获得所需的更新数据输出。

df$DateTime45 <- as.POSIXct(round(as.numeric(df$DateTime)/(45*60))*
                           (45*60),origin='1970-01-01', tz = 'UTC')

df
#             DateTime          DateTime45
#1 2016-08-23 00:22:23 2016-08-23 00:00:00
#2 2016-08-23 00:26:38 2016-08-23 00:45:00
#3 2016-08-23 01:04:12 2016-08-23 00:45:00
#4 2016-08-23 02:27:58 2016-08-23 02:15:00
#5 2016-08-23 03:04:31 2016-08-23 03:00:00
#6 2016-08-23 04:51:46 2016-08-23 04:30:00

原始答案

在基准R中,一种方法是创建45分钟间隔并使用cut / findInterval

TimeIntervalLimits <- seq(as.POSIXct("2016-08-23 00:00:00", tz = 'UTC'), 
                    as.POSIXct("2016-08-24 00:45:00", tz = 'UTC'), by = "45 min")
df$DateTime45 <- cut(df$DateTime, TimeIntervalLimits)
#Or with `findInterval`
#df$DateTime45 <- TimeIntervalLimits[findInterval(df$DateTime, TimeIntervalLimits)]

df
#             DateTime          DateTime45
#1 2016-08-23 00:22:23 2016-08-23 00:00:00
#2 2016-08-23 01:04:12 2016-08-23 00:45:00
#3 2016-08-23 02:27:58 2016-08-23 02:15:00
#4 2016-08-23 03:04:31 2016-08-23 03:00:00
#5 2016-08-23 04:51:46 2016-08-23 04:30:00

如注释中所述,cut从向量的最小值开始休息。因此,一种破解方法是在向量​​中插入一个虚假的时间戳记,从该位置开始中断,然后将cutbreaks参数一起使用。这样可以避免创建TimeIntervalLimits向量。

df$DateTime45 <- cut(c(as.POSIXct('2016-08-23 00:00:00', tz = 'UTC'), 
                     df$DateTime), '45 mins')[-1]