融化每年每小时的数据以按月创建每日平均值,然后绘制以进行比较

Melt yearly hourly data to create daily averages by month then plot for comparison

我有一个多阶段的问题,我一直在尝试使用现有的线程来解决,但我还没有完全有效,所以我想在这里提出。由于我要处理的数据量很大,我正在从 excel 过渡到 R。我有一些 R 方面的背景知识,但下面的大部分内容都是从各种堆栈 post 中拼凑而成的,所以如果有不同的方法来解决这个问题,我会洗耳恭听。

我的原始数据连续多年出现在 25 列(日期和一天中的 24 个单独的小时),如下例所示:

date_seq <- seq(as.POSIXct("2012-01-01"), 
                as.POSIXct("2015-02-01"), 
                by=("hour"))
df <- data.frame(Date = strftime(date_seq, format="%Y-%m-%d"),
                 replicate(24,sample(1:9,27049,rep=TRUE)))

headers<-c("Date", "1:00 AM", "2:00 AM","3:00 AM", "4:00 AM","5:00 AM", "6:00 AM","7:00 AM", "8:00 AM","9:00 AM", "10:00 AM","11:00 AM", "12:00 PM","1:00 PM", "2:00 PM","3:00 PM", "4:00 PM","5:00 PM", "6:00 PM","7:00 PM", "8:00 PM","9:00 PM", "10:00 PM","11:00 PM", "12:00 AM")
colnames(df)<-headers

最终目标:按月计算平均小时值,为每个月创建一个“平均天数”,这样我最终就可以逐月、逐季、逐年比较“平均天数”。例如,对于完成的数据,我可以做如下图所示的事情(只是最终数据的一个例子,尽管我需要用它做一些其他的计算)。

Chart to demonstrate final data form

To that end here is what I have done so far and the associated problems:
library(readr)
library(lubridate)
library(tidyr)
library(dplyr)
library(plyr)
library(ggplot2)
library(reshape2)
library(chron)

df2<-melt(df,variable.name="Time",value.name = "Load",id.vars = c("Date"))
times<- as.POSIXct(df2$Time, format = "%I:%M %p", tz = "GMT")
df2$Time<-times(strftime(times, format = "%H:%M:%S", tz = "GMT"))

df3<-as.data.frame(df2)
df3<-separate(data = df3, col = Date, into = c("Year", "Month","Day"), sep = "\-",remove=FALSE)

在这一点上似乎不错,但现在试图创造那些平均日子是我陷入困境的地方。当我 运行 下面的代码时,它会按月创建小时平均值。不幸的是,这也使日期和日期列变成了 NA,这对于最终比较和后续计算来说并不是什么大问题,但显然我没有做对。我试图减去列,但最终出现错误。

df_month<- df3 %>% 
  group_by(Month, Year, Time) %>%
  summarise_each(funs(mean(.,na.rm=TRUE)))

在此之后,我真的很难从这种长格式中恢复平均天数。本质上,我需要取 2012 年 1 月的平均小时数 1,然后将其与其他小时数的平均值再次组合,并重复所有月份。

我试着回到原始数据的宽格式,但在 ggplot2 中绘制线图时出现了问题,即使我可以在 excel 中绘制这些线的宽格式。我也试过搞乱一些 for 循环来创建平均天数的向量,但无济于事。

抱歉这么久了 post 我非常感谢您对我目前采取的方法以及我应该如何进行的见解。

我在您的代码中没有发现任何严重错误,所以只需清理一下即可。

例如,您可以使用 tidyrgather 而不是旧的 melt,我会使用 dplyr::mutatelubridateyear()month()hour() 而不是 separate,最后是 summarize_at,而不是 summarize_each(现已弃用并创建 NAs).

library(dplyr)
library(tidyr)
library(lubridate)

df_month <- df %>% 
    gather(hours, Load, -Date) %>% 
    mutate(year  = year(Date),
           month = month(Date, label = TRUE),
           hour  = hour(as.POSIXct(hours, format = '%I:%M %p'))) %>% 
    group_by(year, month, hour) %>% 
    summarise_at(vars(Load), mean, na.rm = TRUE)

从这个 data.frame 创建一个 ggplot 很容易,唯一需要注意的是 color aes 必须映射到两个变量,并且这就是为什么我们使用 interaction:

library(ggplot2)
ggplot(df_month) +
    geom_line(aes(hour, Load, color = interaction(month, year, sep = '-'))) +
    scale_y_continuous(limits = c(2, NA)) +
    scale_colour_discrete('')

(数据已在图中 filter 编辑以匹配示例,还因为数据是随机噪声,导致图表难看)