【问题标题】:How to round dates and times to dates and times in 45-minute intervals如何以 45 分钟的间隔将日期和时间四舍五入到日期和时间
【发布时间】:2019-12-30 07:49:36
【问题描述】:

我有一个数据框,其中包含一个名为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

提前致谢

【问题讨论】:

  • 圆到最近。或者等效地,添加 22.5 分钟然后向下取整。

标签: r rounding lubridate posixct


【解决方案1】:

编辑

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

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

如 cmets 中所述,cut 从向量中的最小值开始中断。因此,一种技巧是在我们想要开始中断的向量中插入一个假时间戳,然后使用cutbreaks 参数。这避免了创建TimeIntervalLimits 向量。

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

【讨论】:

  • 感谢@Ronak Shah。那么,据您所知,没有直接的方法来舍入DateTime 以获取变量DateTime45,不是吗?最简单的方法是使用所需的TimeIntervalLimits 创建一个向量,然后合并两个 data.frame。对吗?
  • @Dekike 据我所知,是的,因为所有这些方法都从DateTime 的最小值开始休息,即2016-08-23 00:22:23,而不是你想要的2016-08-23 00:00:00cut(df$DateTime, "45 mins") 工作方式相同。
  • @Dekike 虽然我不确定round_date 发生了什么。我希望它能够按照您的期望工作。不太明白为什么它会舍入到2016-08-23 01:00:00 for 2016-08-23 01:04:12
  • 感谢@Ronak Shah。我能问你一件事吗?在帖子问题中,我包含了单词Round,这意味着我想要它,例如,2016-08-23 00:22:23 被归类为2016-08-23 00:00:00,但2016-08-23 00:28:17(不包括在我的示例中)被归类为2016-08-23 00:45:00。我的意思是,我希望每个DateTime 都转换为DateTime45,但要考虑到哪个TimeIntervalLimit 是最接近的。现在我意识到,在我的示例中,我无法检查您的代码是否也在这样做,但是当我将它与我的真实数据一起使用时,我意识到了这一点。你能告诉我怎么做吗?
  • * 我在df (2016-08-23 00:26:38) 中添加了额外的一行,以检查代码是否正常工作,将DateTime 舍入到最接近的TimeIntervalLimit
猜你喜欢
  • 2013-10-17
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
  • 2012-03-29
  • 2011-03-28
  • 2015-11-27
相关资源
最近更新 更多