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

556 views Asked by At

I have hourly timeseries data of three homes(H1, H2, H3) for continuous five days created as

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

Now I want to plot data homewise in facet form; accordingly I melt dataframe as

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

Within each facet (for each home), I want to see the values of all the five days in line plot form (each facet should contain 5 lines corresponding to different days). Accordingly,

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)

I have forced the same timestamp for all the days of a home to make plotting simple. With above code, I get plot as enter image description here

Only problem with above plot is that, It is plotting same data in all the facets. Ideally, H1 facet should contain data of home 1 only and H2 facet should contain data of home 2. I know that I am not able to pass homewise data in geom_line(), can anyone help to do in correct manner.

1

There are 1 answers

0
Mark Peterson On BEST ANSWER

I think that you may find it more efficient to modify the data outside the call to ggplot rather than inside it (allows closer inspection of what is happening at each step, at least in my opinion).

Here, I am using lubridate to generate two new columns. The first holds only the date (and not the time) to allow faceting on that. The second holds the full datetime, but I then modify the date so that they are all the same. This leaves only the times as mattering (and we can suppress the chosen date in the plot).

library(lubridate)

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

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

Then, I can pass that modified data.frame to ggplot. You will likely want to modify colors/labels, but this should get you a pretty good start.

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")

Generates:

enter image description here