【问题标题】:How to aggregate the hourly rainfall data data into 24hr series如何将每小时降雨数据数据聚合成 24 小时系列
【发布时间】:2021-02-20 05:24:39
【问题描述】:

我的数据框如下

df <- tibble::tribble(
              ~date, ~pcp,
   "9/27/2017 9:00",    0,
  "9/27/2017 10:00",    0,
  "9/27/2017 11:00",    0,
  "9/27/2017 12:00",    0,
  "9/27/2017 13:00",    0,
  "9/27/2017 14:00",    0,
  "9/27/2017 15:00",    0,
  "9/27/2017 16:00",    0,
  "9/27/2017 17:00",    0,
  "9/27/2017 18:00",    0,
  "9/27/2017 19:00",    0,
  "9/27/2017 20:00",    0,
  "9/27/2017 21:00",    0,
  "9/27/2017 22:00",    0,
  "9/27/2017 23:00",    0,
   "9/28/2017 0:00",    0,
   "9/28/2017 1:00",    0,
   "9/28/2017 2:00",    0,
   "9/28/2017 3:00",    0,
   "9/28/2017 4:00",    0,
   "9/28/2017 5:00",    0,
   "9/28/2017 6:00",    0,
   "9/28/2017 7:00", 0.15,
   "9/28/2017 8:00", 8.76,
   "9/28/2017 9:00", 0.02,
  "9/28/2017 10:00",    0,
  "9/28/2017 11:00",    0,
  "9/28/2017 12:00",    0,
  "9/28/2017 13:00",    0,
  "9/28/2017 14:00",    0,
  "9/28/2017 15:00",    0,
  "9/28/2017 16:00",    0,
  "9/28/2017 17:00",    0,
  "9/28/2017 18:00",    0,
  "9/28/2017 19:00",    0,
  "9/28/2017 20:00",    0,
  "9/28/2017 21:00",    0,
  "9/28/2017 22:00",    0,
  "9/28/2017 23:00",    0,
   "9/29/2017 0:00",    0,
   "9/29/2017 1:00",    0,
   "9/29/2017 2:00",    0,
   "9/29/2017 3:00",    0,
   "9/29/2017 4:00",    0,
   "9/29/2017 5:00",    0,
   "9/29/2017 6:00",    0,
   "9/29/2017 7:00",    0,
   "9/29/2017 8:00", 0.31
  )

我想要每天汇总数据(总和)。而不是从同一天的 00:00 到 23:59 聚合,我希望它的初始时间从 i 的 09:00 开始到 i + 1 的 08:59 结束(24 小时后)。

输出是欲望如下

9/28/2017,8.91
9/29/2017,0.33

我是在 Excel 中手动完成的,我不确定要使用什么代码来解决这个问题。 提供的示例是长数据帧的摘录。 谢谢...

【问题讨论】:

  • 您能否添加有关您正在寻找的输出的更多详细信息?
  • 所以你要对一整天的数据求和?

标签: r


【解决方案1】:

如果你想要每个日期的数据

library(tidyverse)
library(lubridate)
df %>% 
    mutate(datetime = parse_date_time(date, "mdy H:M"),
           date = date(datetime)) %>%
    group_by(date) %>%
    summarise(sum_pcp = sum(pcp))

会产生

# A tibble: 3 x 2
  date       sum_pcp
  <date>          <dbl>
1 2017-09-27       0   
2 2017-09-28       8.93
3 2017-09-29       0.31

如果您想从 9:00 计数到第二天的 9:00,您可以通过从原始 datetime 对象中减去 9 小时来引入 subjective_day

df %>% 
  mutate(datetime = parse_date_time(date, "mdy H:M"),
         date = date(datetime),
         initial_day = date(first(date)),
         time = hour(datetime),
         subjective_day = datetime - hours(9)) %>%
  group_by(subjective_day = floor_date(subjective_day, "1 day")) %>% 
  summarise(sum_pcp = sum(pcp))

会产生


  subjective_day      sum_pcp
  <dttm>                <dbl>
1 2017-09-27 00:00:00    8.91
2 2017-09-28 00:00:00    0.33

您的主观日期总是会落后 1 天,因此您可以对此进行调整,或者记住世界上有 9 小时时差的某个地方实际上会将其作为正确的日期时间 :)

【讨论】:

  • 非常感谢最后一个选项是我正在寻找的那个
【解决方案2】:

使用基础 R 和 data.table 的解决方案(当性能很重要或作为 dplyr 和/或 lubridate 的替代品时,它通常效果更好):

第 1 步:设置和创建 R 数据框

library(data.table)

mydt = fread(input = "date,pcp
 9/27/2017 9:00,0
 9/27/2017 10:00,0
 9/27/2017 11:00,0
 9/27/2017 12:00,0
 9/27/2017 13:00,0
 9/27/2017 14:00,0
 9/27/2017 15:00,0
 9/27/2017 16:00,0
 9/27/2017 17:00,0
 9/27/2017 18:00,0
 9/27/2017 19:00,0
 9/27/2017 20:00,0
 9/27/2017 21:00,0
 9/27/2017 22:00,0
 9/27/2017 23:00,0
 9/28/2017 0:00,0
 9/28/2017 1:00,0
 9/28/2017 2:00,0
 9/28/2017 3:00,0
 9/28/2017 4:00,0
 9/28/2017 5:00,0
 9/28/2017 6:00,0
 9/28/2017 7:00,0.15
 9/28/2017 8:00,8.76
 9/28/2017 9:00,0.02
 9/28/2017 10:00,0
 9/28/2017 11:00,0
 9/28/2017 12:00,0
 9/28/2017 13:00,0
 9/28/2017 14:00,0
 9/28/2017 15:00,0
 9/28/2017 16:00,0
 9/28/2017 17:00,0
 9/28/2017 18:00,0
 9/28/2017 19:00,0
 9/28/2017 20:00,0
 9/28/2017 21:00,0
 9/28/2017 22:00,0
 9/28/2017 23:00,0
 9/29/2017 0:00,0
 9/29/2017 1:00,0
 9/29/2017 2:00,0
 9/29/2017 3:00,0
 9/29/2017 4:00,0
 9/29/2017 5:00,0
 9/29/2017 6:00,0
 9/29/2017 7:00,0
 9/29/2017 8:00,0.31")

第 2 步:将日期和时间解析为包含时间戳的新列 ts

mydt[, ts := as.POSIXct(date, format="%m/%d/%Y %H:%M")]

第 3 步:根据问题中描述的规则计算时间间隔并在每个间隔中放置日期。

定义边界(以秒为单位,使用纪元 - 见下文)包含从第 9 小时开始和结束的帧中的所有日期:

epoch_start = as.integer(format(trunc(min(mydt$ts), "day") - (24 - 9) * 60 * 60, "%s"))
epoch_end = as.integer(format(trunc(max(mydt$ts), "day") + (24 + 9) * 60 * 60, "%s"))

Epoch 是自 1970 年 1 月 1 日以来经过的秒数 - 有关详细信息,请向下滚动到 什么是 epoch 时间? here

计算出包含框架中所有日期的时间间隔后,我们可以使用基数 R 从第 9 小时开始构建自定义的 24 小时间隔:

time_seconds_intervals = seq(epoch_start, epoch_end, 60 * 60 * 24)

如果您想查看任何纪元值背后的日期和时间,请使用包anytime

anytime::anytime(epoch_start)
[1] "2017-09-26 09:00:00 CDT"

anytime::anytime(epoch_end)
[1] "2017-09-30 09:00:00 CDT"

对于我们刚刚建立的区间:

anytime::anytime(time_seconds_intervals)
[1] "2017-09-26 09:00:00 CDT" "2017-09-27 09:00:00 CDT" "2017-09-28 09:00:00 CDT" "2017-09-29 09:00:00 CDT"
[5] "2017-09-30 09:00:00 CDT"

第 4 步:使用 findInterval 将每一行分配给它所属的区间并创建新列 day_group

mydt[, day_group := findInterval(as.integer(format(ts, "%s")), time_seconds_intervals)]

第 5 步:按新定义的day_group 进行分组总结

mydt[, .(date_group = min(ts), sum_pcp = sum(pcp)), by=day_group]

产生:

   day_group          date_group sum_pcp
1:         2 2017-09-27 09:00:00    8.91
2:         3 2017-09-28 09:00:00    0.33

附: 我尝试使用anytime 在上面的步骤 2 中解析日期,但不幸的是,由于您的字符串中使用了个位数的小时数,它失败了。 anytimelubridate 或基本 R 提供的解析日期要快得多(存在许多示例,这是我最近发布的一个:https://stackoverflow.com/a/44183836/59470),但除非您将小时数更改为始终包含 2 位数字,例如 09 它不适用于您的数据。如果您确实更改了它,这就是第 2 步的样子:

mydt[, ts := anytime::anytime(date)]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    • 2019-12-29
    相关资源
    最近更新 更多