I have the following data:
> Data
Date Start End
1 2011-11-15 12:01:27 12:30:15
2 2011-11-16 12:01:25 12:32:15
3 2011-11-17 12:01:02 12:39:12
4 2011-11-19 12:01:12 12:30:18
to which I've also appended a Duration column
Data[,4] <- as.numeric(difftime(Data$End,Data$Start))
names(Data)[4] <- "Duration"
I have in my head a visualization for Start,End that looks kind of like a stock candlestick or OHLC chart, where the x value is the Date, and y is End - Start.
End is at the top with a rectangle descending down to Start---the height of the rectangle changes over time with the Duration. That is, each Date has a different rectangle height determined by the difference between Start and End.
The x axis, here, goes from 2011-11-15 to 2011-11-19. The y axis goes from 12:00:00 to 12:40:00.
Do any ggplot wizards see an easy way to do this? Since both Start and End are changing over time, would I have to use geom_ribbon or geom_polygon rather than geom_bar or geom_area?
It would be extra cool if the color of the bar can change to red on days when the value of Duration is greater than 2 standard deviations!
I use a similar structure to nico (thanks!):
date = c("2011-11-15", "2011-11-16", "2011-11-17", "2011-11-19")
start = c("12:01:27", "12:01:25", "12:01:02", "12:01:12")
end = c("12:30:15", "12:32:15", "12:39:12", "12:30:18")
Next, we put it in a data frame that contains the corners of the rectangles:
##I've made the rectangles 2 hours wide
df = data.frame(date = as.POSIXct(date),
ystart = as.POSIXct(start, format="%H:%M:%S"),
yend = as.POSIXct(end, format="%H:%M:%S"),
xstart=as.POSIXct(paste(date, "12:00:00"), format="%Y-%m-%d %H:%M:%S"),
xend = as.POSIXct(paste(date, "14:00:00"), format="%Y-%m-%d %H:%M:%S"))
Then we just use geom_rect
:
ggplot() + geom_rect(data=df, aes(ymin=ystart, ymax=yend,
xmin=xend, xmax=xstart))
If you want to make some of them red based on a condition, just create an additional column on your data frame:
##Your condition is something to do with the sd
df$isRed = c(TRUE, FALSE)
Then add two ggplot layers:
ggplot() + geom_rect(data=subset(df, !isRed), aes(ymin=ystart, ymax=yend,
xmin=xend, xmax=xstart)) +
geom_rect(data=subset(df, isRed), aes(ymin=ystart, ymax=yend,
xmin=xend, xmax=xstart), colour="red")
Example graph
I don't use ggplot, but I can give you a base R solution
# Generate the data
date <- c("2011-11-15", "2011-11-16", "2011-11-17", "2011-11-19")
start <- c("12:01:27", "12:01:25", "12:01:02", "12:01:12")
end <- c("12:30:15", "12:32:15", "12:39:12", "12:30:18")
# Put everything in a data frame and convert to POSIXct objects
# The times will be all converted to today's date
# but this will not influence the plot
df <- data.frame(date = as.POSIXct(date),
start = as.POSIXct(start, format="%H:%M:%S"),
end = as.POSIXct(end, format="%H:%M:%S"))
# Get the working range for the axes in order to make them nicer (see below)
x.from <- as.POSIXct(min(date))
x.to <- as.POSIXct(max(date))
y.from <- as.POSIXct(min(start), format="%H:%M:%S")
y.to <- as.POSIXct(max(end), format="%H:%M:%S")
# Create an empty plot, as rect will not create a new one
# We put no axes on the plot
plot(0, "n", xaxt="n", yaxt="n", ylab="", xlab="Day",
ylim=c(from, to), xlim=range(df$date))
# Now draw the rectangles (I made them 2 hours-wide)
rect(df$date-3600, df$start, df$date+3600, df$end, col="black")
days <- seq(x.from, x.to, 24*3600)
times <- seq(y.from, y.to, 300) # 5 min (=300 s) axis ticks
# Finally add the axes
axis(1, at=days, labels=strftime(days, "%d/%m"))
axis(2, at=times, labels=strftime(times, "%H:%M"), las=1)
The result:
来源:https://stackoverflow.com/questions/10310163/time-series-visualization-for-start-end-duration-in-r