问题
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
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:
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:
来源:https://stackoverflow.com/questions/41223012/plot-multiple-days-data-of-multiple-homes-in-facet-form-of-ggplot