【问题标题】:How to calculate average of a variable by hour in R如何在R中按小时计算变量的平均值
【发布时间】:2025-12-28 11:35:10
【问题描述】:

我在尝试按小时计算平均温度时遇到了麻烦。

我有一个包含日期时间(hh:mm:ss p.m./a.m.)和温度的数据框。 我需要的是按小时提取平均温度,以便绘制温度的每日变化。

我是 R 新手,但尝试了我所知道的:我首先尝试将小时数转换为数字,然后提取前两个字符,然后计算平均值,但效果不佳。此外,我有很多文件要分析,如果有比我找到的“解决方案”更自动化和更干净的东西会更好。

我相信这一定是在 R 中按小时计算平均值的更好方法,因此我一直在此处的其他帖子中寻找答案。不幸的是,我找不到关于从时间数据中提取统计数据的明确答案。

我的数据是这样的

          date     hour temperature
1   28/12/2013 13:03:01      41.572
2   28/12/2013 13:08:01      46.059
3   28/12/2013 13:13:01       48.55
4   28/12/2013 13:18:01      49.546
5   28/12/2013 13:23:01      49.546
6   28/12/2013 13:28:01      49.546
7   28/12/2013 13:33:01      50.044
8   28/12/2013 13:38:01      50.542
9   28/12/2013 13:43:01      50.542
10  28/12/2013 13:48:01       51.04
11  28/12/2013 13:53:01      51.538
12  28/12/2013 13:58:01      51.538
13  28/12/2013 14:03:01      50.542
14  28/12/2013 14:08:01       51.04
15  28/12/2013 14:13:01       51.04
16  28/12/2013 14:18:01      52.534
17  28/12/2013 14:23:01      53.031
18  28/12/2013 14:28:01      53.031
19  28/12/2013 14:33:01      53.031
20  28/12/2013 14:38:01      51.538
21  28/12/2013 14:43:01      53.031
22  28/12/2013 14:48:01      53.529
etc (24hs data)

我希望 R 计算每小时的平均值(不考虑分钟或秒的差异,仅按小时计算)

有什么建议吗? 非常感谢您!

问候, 玛丽亚

【问题讨论】:

    标签: r time average


    【解决方案1】:

    将日期和小时列组合成一个 POSIXct 列和 cut() 按小时休息:

    df <- read.table(header=TRUE, stringsAsFactors=FALSE, text="
    date hour temperature
    28/12/2013 13:03:01  41.572
    28/12/2013 13:08:01  46.059
    28/12/2013 13:13:01  48.55
    28/12/2013 13:18:01  49.546
    28/12/2013 13:23:01  49.546
    28/12/2013 13:28:01  49.546
    28/12/2013 13:33:01  50.044
    28/12/2013 13:38:01  50.542
    28/12/2013 13:43:01  50.542
    28/12/2013 13:48:01  51.04
    28/12/2013 13:53:01  51.538
    28/12/2013 13:58:01  51.538
    28/12/2013 14:03:01  50.542
    28/12/2013 14:08:01  51.04
    28/12/2013 14:13:01  51.04
    28/12/2013 14:18:01  52.534
    28/12/2013 14:23:01  53.031
    28/12/2013 14:28:01  53.031
    28/12/2013 14:33:01  53.031
    28/12/2013 14:38:01  51.538
    28/12/2013 14:43:01  53.031
    28/12/2013 14:48:01  53.529
    28/12/2013 15:01:01  50.77")
    
    df$datehour <- cut(as.POSIXct(paste(df$date, df$hour),
       format="%d/%m/%Y %H:%M:%S"), breaks="hour") 
    head(df)
            date     hour temperature            datehour
    1 28/12/2013 13:03:01      41.572 2013-12-28 13:00:00
    2 28/12/2013 13:08:01      46.059 2013-12-28 13:00:00
    3 28/12/2013 13:13:01      48.550 2013-12-28 13:00:00
    4 28/12/2013 13:18:01      49.546 2013-12-28 13:00:00
    5 28/12/2013 13:23:01      49.546 2013-12-28 13:00:00
    6 28/12/2013 13:28:01      49.546 2013-12-28 13:00:00
    

    现在按每小时列汇总:

    means <- aggregate(temperature ~ datehour, df, mean)
    head(means)
                 datehour temperature
    1 2013-12-28 13:00:00    49.17192
    2 2013-12-28 14:00:00    52.23470
    3 2013-12-28 15:00:00    50.77000
    
    plot(as.POSIXct(means$datehour), means$temperature, type="l", las=1,
         main="Hourly Avg Temperatures", xlab="Hour", ylab="")
    

    但是,对于时间序列数据,我喜欢使用包 xts:

    require(xts)
    df.xts <- xts(df$temperature, as.POSIXct(paste(df$date, df$hour),
          format="%d/%m/%Y %H:%M:%S"))
    head(df.xts)
                          [,1]
    2013-12-28 13:03:01 41.572
    2013-12-28 13:08:01 46.059
    2013-12-28 13:13:01 48.550
    2013-12-28 13:18:01 49.546
    2013-12-28 13:23:01 49.546
    2013-12-28 13:28:01 49.546
    
    means <- period.apply(df.xts, endpoints(df.xts, "hours"), mean)
    head(means)
                            [,1]
    2013-12-28 13:58:01 49.17192
    2013-12-28 14:48:01 52.23470
    2013-12-28 15:01:01 50.77000
    

    注意时间戳是每小时的最后一个条目。我们可以使用这个函数将时间戳(向下)对齐到小时的开始:

    align.time.down = function(x,n){ index(x) = index(x)-n; align.time(x,n) }
    means.rounded <- align.time.down(means, 60*60)  
             # 2nd argument is the number of seconds to adjust/round to,
             # just like function align.time()
    
    head(means.rounded)
                            [,1]
    2013-12-28 13:00:00 49.17192
    2013-12-28 14:00:00 52.23470
    2013-12-28 15:00:00 50.77000
    
    plot(means.rounded, las=1, main="Hourly Avg Temperatures")
    

    【讨论】:

    • 当我按那个每小时列进行聚合时,我遇到错误消息( Error in get(as.character(FUN), mode = "function", envir = envir) : object 'FUN'未找到模式“功能”)。我该如何解决?
    【解决方案2】:

    如果在问题中给出示例数据和预期输出,总是会更容易。

    Data.table 包的解决方案

    require(data.table)
    data <- fread('temp.csv',sep=',') #Assuming your data is in temp.csv
    #if above step not executed, convert the data frame to data.table 
    data <- data.table(data)
    > str(data)
    Classes ‘data.table’ and 'data.frame':  12 obs. of  3 variables:
    $ date       : chr  "28/12/2013" "28/12/2013" "28/12/2013" "28/12/2013" ...
    $ hour       : chr  "13:03:01" "13:08:01" "13:13:01" "13:18:01" ...
    $ temperature: num  41.6 46.1 48.5 49.5 49.5 ...
    
    > data
          date     hour    temperature      avg
    1: 27/12/2013 13:00:00       42.99 35.78455
    2: 27/12/2013 14:00:00       65.97 35.78455
    3: 27/12/2013 15:00:00       63.57 35.78455 
    
      data[,list(avg=mean(temperature)),by=hour] #dataset is sorted by hour
        hour   avg
    1: 13:00:00 42.99
    2: 14:00:00 65.97
    3: 15:00:00 63.57
      data[,list(avg=mean(temperature)),by="date,hour"] #data set is grouped by date,then hour
            date     hour   avg
    1: 27/12/2013 13:00:00 42.99
    2: 27/12/2013 14:00:00 65.97
    3: 27/12/2013 15:00:00 63.57
    
    data[,list(avg=mean(temperature)),by=list(date,hour(as.POSIXct(data$hour, format = "%H:%M:%S")))] # to group by hour only 
         date     hour    avg
    1: 27/12/2013    1 29.530
    2: 27/12/2013    4 65.970
    

    【讨论】:

    • 很抱歉没有更具体。我也在学习如何发布我的问题。谢谢你的建议。我会根据你的回答编辑我的问题。
    • 我仍然对你的问题感到困惑。我的回答能解决你的问题吗?您只想对小时进行分组(不包括分钟和秒)
    • 没错,我试过你的脚本,但我收到了这个错误消息 [.data.frame(data, , list(avg = mean(temperature)), by = hour) 中的错误:未使用的参数(by = hour ) 我正在更深入地寻找我收到该错误消息的原因
    • 您收到该错误是因为,它是一个数据框。我假设你没有使用 fread 来读取数据,在这种情况下, data
    • 你是对的!我照你说的做了,但我不相信这些价值观。例如,我得到了 13:00hs 的平均温度为 65 度,这是不可能的,因为样本值(范围从 41.572 到 51.538 度)。你得到了同样的结果吗?很奇怪。