以ggplot的Facet形式绘制多个房屋的多天数据

Plot multiple days data of multiple homes in Facet form of ggplot

我有三个家庭(H1, H2, H3)连续五天的每小时时间序列数据创建为

library(xts)
library(ggplot2)
set.seed(123)
dt <- data.frame(H1 = rnorm(24*5,200,2),H2 = rnorm(24*5,150,2),H3 = rnorm(24*5,50,2)) # hourly data of three homes for 5 days
timestamp <- seq(as.POSIXct("2016-01-01"),as.POSIXct("2016-01-05 23:59:59"), by = "hour") # create timestamp
dt$timestamp <- timestamp

现在我想以分面形式在家中绘制数据;因此我将数据框融化为

tempdf <- reshape2::melt(dt,id.vars="timestamp") # melt data for faceting
colnames(tempdf) <- c("time","var","val") # rename so as not to result in conflict with another melt inside geom_line

在每个方面(对于每个家庭),我想以线图形式查看所有五天的值(每个方面应包含对应于不同日期的 5 条线)。因此,

ggplot(tempdf) + facet_wrap(~var) + 
  geom_line(data = function(x) {
    locdat <- xts(x$val,x$time)# create timeseries object for easy splitting
    sub <- split.xts(locdat,f="days") # split data daywise of considered home
    sub2 <- sapply(sub, function(y) return(coredata(y))) # arrange data in matrix form
    df_sub2 <- as.data.frame(sub2)
    df_sub2$timestamp <- index(sub[[1]]) # forcing same timestamp for all days [okay with me]
    df_melt <- reshape2::melt(df_sub2,id.vars="timestamp") # melt to plot inside each facet
    #return(df_melt)
    df_melt
  }, aes(x=timestamp, y=value,group=variable,color=variable),inherit.aes = FALSE)

为了让绘图变得简单,我强制在家里的所有日子使用相同的时间戳。使用上面的代码,我得到了 plot as

上图的唯一问题是,它在所有方面绘制相同的数据。理想情况下,H1 facet 应该只包含 home 1 的数据,H2 facet 应该包含 home 2 的数据。我知道我无法在 geom_line() 中传递 homewise 数据,谁能帮忙以正确的方式去做。

我认为您可能会发现在对 ggplot 的调用之外 修改数据比在调用 ggplot 内部修改数据更有效(允许更仔细地检查正在发生的事情每一步,至少在我看来是这样)。

在这里,我使用 lubridate 生成两个新列。第一个只包含日期(而不是时间)以允许对其进行分面。第二个包含完整的日期时间,但我随后修改了日期,使它们都相同。这只留下重要的时间(我们可以在图中隐藏所选日期)。

library(lubridate)

tempdf$day <- date(tempdf$time)
tempdf$forPlotTime <- tempdf$time

date(tempdf$forPlotTime) <-
  "2016-01-01"

然后,我可以将修改后的 data.frame 传递给 ggplot。您可能想要修改 colors/labels,但这应该会给您一个很好的开始。

ggplot(tempdf
       , aes(x = forPlotTime
             , y = val
             , col = as.factor(day))) +
  geom_line() +
  facet_wrap(~var) +
  scale_x_datetime(date_breaks = "6 hours"
                   , date_labels = "%H:%M")

生成: