Solution for Annotating in ggplots with POSIXct class data
is Given Below:
I’m looking for help annotating or creating a legend for 2 subsets of data from the same df on a geom-line plot. The difficulties appear to be because I have POSIXct data on my X-axis. I found a question about the same issue but no clear answer and possibly a bug yet to be addressed – How to use ggplot2’s annotate with dates in x-axis?
My plot summarises the median time spent by patients (
left.true) in an hospital ward across according to the time of arrival onto the ward using data collected over several weeks. The time spent differs according to time of arrival (
start.time) and the area of the ward they arrive into (
INITIAL.AREA) so needs to be visualised as two separate lines but plotted together across time for client understanding – hence two geom_line subsets.
Apologies for the inelegant code, but creating the plot crequires time of arrival from one of 2 vectors with a preference for the variable
Add.Time unless it is not recorded (i.e.,
NA), at which point it sets
start.time according to an alternative variable.
los.plot <- ggplot() + geom_line(data = los2 %>% filter(INITIAL.AREA == "AMU") %>% mutate(start.time = case_when( !is.na(Adm.Time) ~ Adm.Time, is.na(Adm.Time) ~ Ward.Start.Time..in.Bed.)) %>% select(start.time, left.true) %>% group_by(start.time) %>% summarise(median = median(left.true)), aes(x=start.time, y=(median/60)), color="grey30") + geom_line(data = los2 %>% filter(INITIAL.AREA == "AAA") %>% mutate(start.time = case_when( !is.na(Adm.Time) ~ Adm.Time, is.na(Adm.Time) ~ Ward.Start.Time..in.Bed.)) %>% select(start.time, left.true) %>% group_by(start.time) %>% summarise(median = median(left.true)), aes(x=start.time, y=(median / 60)), color="magenta") + labs(title = "Median LoS according to initial area of care", subtitle = "(Data from October 2019: n=1409)", #NAs removed caption = c("AEC patients","AMU Bedded patients"), x = "Time of arrival onto unit", y = "Median LoS (hours)") + theme(plot.caption = element_text(face = "bold", color = c('magenta', 'grey30'), hjust=c(1, 0))) + scale_x_datetime(breaks = time.breaks, labels = c("00:00", "02:00", "04:00", "06:00", '08:00', '10:00', '12:00','14:00', '16:00', '18:00', '20:00', '22:00', '24:00'))
Trying to use annotate with
los.plot + annotate("text", x =03:00:00, y=1, label = "AEC patients",color="magenta")
Error: Invalid input: time_trans works with objects of class POSIXct only
I’m assuming this is because the x-axis position argument is incompatible with a POSIXct class. I can’t seem to find a way around this.
So far my only solution has been
labs(captions = c(...,...) as a vector as shown in the main code but it’s not an easy plot to understand without a clear legend or labels next to the lines as you can see from the image. I’ve struggled trying to create a legend from scratch as I have two different subsets of data – however, if anyone has a solution to this it would avoid all the POSIX/x-axis dilemma.
Still not further forward with the annotation and time data but I did find out where I was going wrong in creating my own legend – found this post after much searching: How to add a color legend to a ggplot with different geom layers
This explained that to add a legend I needed to put my color into the
aes() argument of
geom_line() and set the colors using scale_fill_manual.
los.plot <- ggplot() + geom_line(data = los2 %>% ... (as above) aes(x=start.time, y=(median/60), color = "AMU Bedded")) + geom_line(data = los2 %>% ... (as above) aes(x=start.time, y=(median / 60), color="AEC")) + labs(title = ... (as above)) + scale_colour_manual(breaks = c("AMU Bedded", "AEC"), values = c("grey30","magenta"))
I had been setting the color outside of the
Which is exactly what I wanted