按中午而不是午夜对日期进行分组

Group dates by midday instead of midnight

我有一个数据集,有些日子每天都有多个集合。我想创建一个可用于捆绑 'days' 的字段,但我想在中午而不是午夜拆分。不幸的是,当我执行 "midday split" 时,日期值是整数而不是日期值。

一些示例代码:

library(tidyverse)
x <- as.POSIXct(Sys.time()) 

y <- as.tibble(x)

#midnights comes through correctly as a date
y %>%
  mutate(midnights=as.Date(value)) 

#middays comes through as an integer instead of a date
y %>%
  mutate(middays=ifelse(as.numeric(format(value,"%H")) >= 12,
                        as.Date(value),
                        as.Date(value)-1)) 

我应该怎么做?

您可以使用的一个技巧是通过调用 as.numeric(x)x 转换为纪元以来的秒数。然后要获得自纪元以来的天数,它只是 as.numeric(x) %/% 86400 (因为一天有 86400 秒)。因此,您可以使用此值按天拆分(即在午夜拆分)。如果你想 'shift' 这 12 小时,你需要做的就是将 x 移动 12 小时,即 运行 as.numeric(dates + 12 * 3600) %/% 86400

例如

dates <- structure(c(1505771227.18457, 1505814427.18457, 1505857627.18457, 
         1505900827.18457, 1505944027.18457, 1505987227.18457, 
         1506030427.18457), class = c("POSIXct", "POSIXt"))
#[1] "2017-09-18 22:47:07 BST" "2017-09-19 10:47:07 BST" "2017-09-19 22:47:07 BST" "2017-09-20 10:47:07 BST"
#[5] "2017-09-20 22:47:07 BST" "2017-09-21 10:47:07 BST" "2017-09-21 22:47:07 BST"

as.numeric(dates) %/% 86400 # use this to group by day (split at midnight)
#[1] 17427 17428 17428 17429 17429 17430 17430

as.numeric(dates + 12 * 3600) %/% 86400 # use this to split at noon
#[1] 17428 17428 17429 17429 17430 17430 17431

或者,如果你想使用 lubridate,你可以玩同样的把戏,即计算 lubridate::floor_date(dates + lubridate::hours(12), 'day') 将日期移动 12 小时,然后找到日期,并以此为基础进行分组。

ifelse returns 一个数字,因为它去除了 class 信息。只需将整个内容包装在另一个 as.Date():

y %>%
  mutate(middays=as.Date(ifelse(as.numeric(format(value,"%H")) >= 12,
                        as.Date(value),
                        as.Date(value)-1),origin="1970-01-01"))

或使用 dplyr 中的 if_else 来解决

y %>%
  mutate(middays=if_else(as.numeric(format(value,"%H")) >= 12,
                        as.Date(value),
                        as.Date(value)-1))

## A tibble: 1 × 2
#                value    middays
#               <dttm>     <date>
#1 2017-09-21 08:28:05 2017-09-19