【问题标题】:Aggregating hourly data into daily aggregates将每小时数据汇总为每日汇总
【发布时间】:2011-07-09 04:43:57
【问题描述】:

我有以下格式的每小时天气数据:

Date,DBT
01/01/2000 01:00,30
01/01/2000 02:00,31
01/01/2000 03:00,33
...
...
12/31/2000 23:00,25

我需要的是这样的 max、min、ave 的每日汇总:

Date,MaxDBT,MinDBT,AveDBT
01/01/2000,36,23,28
01/02/2000,34,22,29
01/03/2000,32,25,30
...
...
12/31/2000,35,9,20

如何在 R 中做到这一点?

【问题讨论】:

  • 下一次,以可读的格式提供数据表,例如使用 dput() 或提供可运行的代码来提供我在回答中显示的数据。
  • 阅读了建议的答案后,我想知道是否不能仅使用基础 R 来完成。

标签: datetime r time aggregate


【解决方案1】:

几个选项:

1。时间k

如果您有数据框(或 tibble),则可以使用来自 timetksummarize_by_time() 函数:

library(tidyverse)
library(timetk)

# Collect Data
text <- "Date,DBT
01/01/2000 01:00,30
01/01/2000 02:00,31
01/01/2000 03:00,33
12/31/2000 23:00,25"

df <- read_csv(text, col_types = cols(Date = col_datetime("%m/%d/%Y %H:%M")))
df
#> # A tibble: 4 x 2
#>   Date                  DBT
#>   <dttm>              <dbl>
#> 1 2000-01-01 01:00:00    30
#> 2 2000-01-01 02:00:00    31
#> 3 2000-01-01 03:00:00    33
#> 4 2000-12-31 23:00:00    25

# Summarize
df %>%
  summarise_by_time(
    .date_var = Date, 
    .by       = "day",
    min       = min(DBT),
    max       = max(DBT),
    mean      = mean(DBT)
  )
#> # A tibble: 2 x 4
#>   Date                  min   max  mean
#>   <dttm>              <dbl> <dbl> <dbl>
#> 1 2000-01-01 00:00:00    30    33  31.3
#> 2 2000-12-31 00:00:00    25    25  25

reprex package (v2.0.0) 于 2021-05-21 创建

2。 Tidyquant

您可以为此使用tidyquant 包。该过程涉及使用tq_transmute 函数返回使用xts 聚合函数apply.daily 修改的数据帧。我们将应用自定义stat_fun,它返回最小值、最大值和平均值。但是,您可以应用任何您喜欢的矢量函数,例如 quantile


library(tidyquant)

df
#> # A tibble: 4 x 2
#>                  Date   DBT
#>                <dttm> <dbl>
#> 1 2000-01-01 01:00:00    30
#> 2 2000-01-01 02:00:00    31
#> 3 2000-01-01 03:00:00    33
#> 4 2000-12-31 23:00:00    25

stat_fun <- function(x) c(min = min(x), max = max(x), mean = mean(x))

df %>%
    tq_transmute(select     = DBT,
                 mutate_fun = apply.daily,
                 FUN        = stat_fun)
# A tibble: 2 x 4
#>                 Date   min   max     mean
#>                <dttm> <dbl> <dbl>    <dbl>
#> 1 2000-01-01 03:00:00    30    33 31.33333
#> 2 2000-12-31 23:00:00    25    25 25.00000

【讨论】:

  • 如果我需要按小时汇总,请告诉我需要什么
  • 每小时,您可以使用timetk::summarize_by_time(.by = "hour")
【解决方案2】:

还有一个不错的包,叫做hydroTSM。它使用zoo对象,可以及时转换为其他聚合

你的函数是subdaily2daily。您可以选择聚合是否应基于 min / max / mean...

【讨论】:

    【解决方案3】:

    鉴于您有 POSIXct 时间格式,您可以使用 as.POSIXct(time) 来执行此操作,您只需要 cut 和 aggregate()。

    试试这个:

    split_hour = cut(as.POSIXct(temp$time), breaks = "60 mins") # summrise given mins
    temp$hour = split_hour # make hourly vaiable
    ag = aggregate(. ~ hour, temp, mean)
    

    在这种情况下,温度是这样的 温度

    1  0.6 0.6 0.0 0.350 0.382 0.000 2020-04-13 18:30:42
    2  0.0 0.5 0.5 0.000 0.304 0.292 2020-04-13 19:56:02
    3  0.0 0.2 0.2 0.000 0.107 0.113 2020-04-13 20:09:10
    4  0.6 0.0 0.6 0.356 0.000 0.376 2020-04-13 20:11:57
    5  0.0 0.3 0.2 0.000 0.156 0.148 2020-04-13 20:12:07
    6  0.0 0.4 0.4 0.000 0.218 0.210 2020-04-13 22:02:49
    7  0.2 0.2 0.0 0.112 0.113 0.000 2020-04-13 22:31:43
    8  0.3 0.0 0.3 0.155 0.000 0.168 2020-04-14 03:19:03
    9  0.4 0.0 0.4 0.219 0.000 0.258 2020-04-14 03:55:58
    10 0.2 0.0 0.0 0.118 0.000 0.000 2020-04-14 04:25:25
    11 0.3 0.3 0.0 0.153 0.160 0.000 2020-04-14 05:38:20
    12 0.0 0.7 0.8 0.000 0.436 0.493 2020-04-14 05:40:02
    13 0.0 0.0 0.2 0.000 0.000 0.101 2020-04-14 05:40:44
    14 0.3 0.0 0.3 0.195 0.000 0.198 2020-04-14 06:09:26
    15 0.2 0.2 0.0 0.130 0.128 0.000 2020-04-14 06:17:15
    16 0.2 0.0 0.0 0.144 0.000 0.000 2020-04-14 06:19:36
    17 0.3 0.0 0.4 0.177 0.000 0.220 2020-04-14 06:23:43
    18 0.2 0.0 0.0 0.110 0.000 0.000 2020-04-14 06:25:19
    19 0.0 0.0 0.0 1.199 1.035 0.251 2020-04-14 07:05:24
    20 0.2 0.2 0.0 0.125 0.107 0.000 2020-04-14 07:21:46
    

    ag是这样的

    ag

    1  2020-04-13 18:30:00 0.60000000 0.6000000 0.0000000 0.3500000 0.38200000 0.00000000
    2  2020-04-13 19:30:00 0.15000000 0.2500000 0.3750000 0.0890000 0.14175000 0.23225000
    3  2020-04-13 21:30:00 0.00000000 0.4000000 0.4000000 0.0000000 0.21800000 0.21000000
    4  2020-04-13 22:30:00 0.20000000 0.2000000 0.0000000 0.1120000 0.11300000 0.00000000
    5  2020-04-14 02:30:00 0.30000000 0.0000000 0.3000000 0.1550000 0.00000000 0.16800000
    6  2020-04-14 03:30:00 0.30000000 0.0000000 0.2000000 0.1685000 0.00000000 0.12900000
    7  2020-04-14 05:30:00 0.18750000 0.1500000 0.2125000 0.1136250 0.09050000 0.12650000
    8  2020-04-14 06:30:00 0.10000000 0.1000000 0.0000000 0.6620000 0.57100000 0.12550000
    9  2020-04-14 07:30:00 0.00000000 0.3000000 0.2000000 0.0000000 0.16200000 0.11800000
    10 2020-04-14 19:30:00 0.20000000 0.3000000 0.0000000 0.1460000 0.19000000 0.00000000
    11 2020-04-14 20:30:00 0.06666667 0.2000000 0.2666667 0.0380000 0.11766667 0.17366667
    12 2020-04-14 22:30:00 0.20000000 0.3000000 0.0000000 0.1353333 0.18533333 0.00000000
    13 2020-04-14 23:30:00 0.00000000 0.5000000 0.5000000 0.0000000 0.28000000 0.32100000
    14 2020-04-15 01:30:00 0.25000000 0.2000000 0.4500000 0.1355000 0.11450000 0.26100000
    

    【讨论】:

      【解决方案4】:

      1) 这可以使用 zoo 紧凑地完成:

      L <- "Date,DBT
      01/01/2000 01:00,30
      01/01/2000 02:00,31
      01/01/2000 03:00,33
      12/31/2000 23:00,25"
      
      library(zoo)
      stat <- function(x) c(min = min(x), max = max(x), mean = mean(x))
      z <- read.zoo(text = L, header = TRUE, sep = ",", format = "%m/%d/%Y", aggregate = stat)
      

      这给出了:

      > z
                 min max     mean
      2000-01-01  30  33 31.33333
      2000-12-31  25  25 25.00000
      

      2)这里是一个只使用core R的解决方案:

      DF <- read.csv(text = L)
      DF$Date <- as.Date(DF$Date, "%m/%d/%Y")
      ag <- aggregate(DBT ~ Date, DF, stat) # same stat as in zoo solution 
      

      最后一行给出:

      > ag
              Date  DBT.min  DBT.max DBT.mean
      1 2000-01-01 30.00000 33.00000 31.33333
      2 2000-12-31 25.00000 25.00000 25.00000
      

      编辑:(1) 自从首次出现以来,read.zootext= 参数被添加到 zoo 包中。 (2) 小改进。

      【讨论】:

      • @Grothendieck : +1 我从来没有意识到你可以通过不在 as.Date() 中指定每小时信息来删除它。
      • 我正在通过电话查看此内容,但我敢打赌 aggregate 解决方案提供了一个列表列,除非您将整个内容包装到 do.call(cbind.data.frame, aggregate... 中,否则您无法真正用于任何事情。
      • 它产生一个data.frame,其第一列为ag$Date. and whose second column is the matrix ag$DBT`,其列为"min""max""mean"。它可以使用read.zoo(ag) 轻松转换为动物园系列。
      【解决方案5】:

      使用 plyr 包中的 strptime()trunc()ddply()

      #Make the data
      ZZ <- textConnection("Date,DBT
      01/01/2000 01:00,30
      01/01/2000 02:00,31
      01/01/2000 03:00,33
      12/31/2000 23:00,25")
      dataframe <- read.csv(ZZ,header=T)
      close(ZZ)
      
      # Do the calculations
      dataframe$Date <- strptime(dataframe$Date,format="%m/%d/%Y %H:%M")
      dataframe$day <- trunc(dataframe$Date,"day")
      
      require(plyr)
      
      ddply(dataframe,.(day),
            summarize,
            aveDBT=mean(DBT),
            maxDBT=max(DBT),
            minDBT=min(DBT)
      )
      

      给予

               day   aveDBT maxDBT minDBT
      1 2000-01-01 31.33333     33     30
      2 2000-12-31 25.00000     25     25
      

      澄清一下:

      strptime 根据格式将字符转换为日期。要了解如何指定格式,请参阅 ?strptime。然后trunc 会将这些日期时间截断为指定的单位,在本例中为天。

      ddply 将根据day 将其拆分后评估数据框中的函数summarizesummarize 之后的所有内容都是传递给函数 summarize 的参数。

      【讨论】:

      • 你真的需要 summarize 的包装器吗?
      • @Sacha :确实,不需要,谢谢纠正。时间不早了……
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多