0

Background: I need to display the time each hospital bed is emptied (via patient discharge) and the time a new patient is placed in the bed, with markers indicating steps taken in between to prepare the bed for the new patient.

Plotting goals: My intention is to have two horizontal bars for each Room/Bed: one (currently in grey) showing the patient who's been discharged, and another (in blue) showing the new patient who's been placed in the same bed.

Question: How can I better display time on the x-axis? I'd be grateful for any referrals to documentation on working with class = "times" data, too.

Sample data:

BedMap <- structure(list(
  Date = structure(c(17210, 17210, 17210, 17210, 17210, 17210, 17210), class = "Date"), 
  RoomBed = c("TestBed1", "TestBed2", "TestBed3", "TestBed4", "TestBed5", "TestBed6", "TestBed7"), 
  UnitGroup = c("Tele", "Tele", "2P", "2P", "3P", "Tele", "ICU"), 
  DcOrderTime = structure(c(0.358333333333333, 0.377777777777778, 0.430555555555556, 0.470833333333333, 0.395833333333333, 0.623611111111111, 0.441666666666667), 
                      format = "h:m:s", class = "times"), 
  DcTime = structure(c(0.457638888888889, 0.475694444444444, 0.5, 0.59375, 0.625, 0.700694444444444, 0.770833333333333), 
                 format = "h:m:s", class = "times"), 
  DecisionTime = structure(c(0.582638888888889, 0.539583333333333, 0.886111111111111, 0.596527777777778, 0.675, 0.653472222222222, 0.777777777777778), 
                       format = "h:m:s", class = "times"), 
  RequestBedTime = structure(c(0.60625, 0.545138888888889, 0.91875, 0.84375, 0.707638888888889, 0.713888888888889, 0.857638888888889), 
                         format = "h:m:s", class = "times"),
  DepartTime = structure(c(0.629166666666667, 0.599305555555556, 0.974305555555556, 0.952083333333333, 0.859722222222222, 0.770138888888889, 0.910416666666667), 
                     format = "h:m:s", class = "times")), 
  class = "data.frame", row.names = c(NA, -7L), 
  .Names = c("Date", "RoomBed", "UnitGroup", "DcOrderTime", "DcTime", "DecisionTime", "RequestBedTime", "DepartTime"))

And current plot, with times displayed as decimals:

enter image description here

ggplot(BedMap) +
  geom_segment(aes(x = 0, #start of light grey bar, indicates bed occupied & discharge planning has not yet started
               y = RoomBed, 
               xend = DcOrderTime, #end of light grey bar
               yend = RoomBed), 
           color = "Light Grey", 
           size = 6) +
  geom_segment(aes(x = DcOrderTime, #start of dark grey bar, indicates bed still occupied but discharge planning has begun
               y = RoomBed, 
               xend = DcTime, #end of dark grey bar, indicates patient has been discharged, bed is unoccupied
               yend = RoomBed), 
               color = "Dark Grey", 
               size = 6) +
  geom_segment(aes(x = DepartTime, #start of blue bar, indicates new patient has been placed in bed
               y = RoomBed, 
               xend = 1, #end of blue bar (set at midnight/end of day)
               yend = RoomBed), 
               color = "Blue", 
               size = 6) +
  geom_point(aes(x = DecisionTime, 
             y = RoomBed), 
         color = "black", size = 3) +
  geom_point(aes(x = RequestBedTime, 
             y = RoomBed), 
         color = "green", size = 3) +
  theme(legend.position = "none") +
  labs(x = "Time", y = "Room-Bed", title = "Daily Bed Map")

When I view the BedMap df, the times show up formatted correctly (eg. DcOrderTime shows up as "08:36:00", "09:04:00", "10:20:00", "11:18:00", "09:30:00", etc.). But the x-axis is displayed as a decimal. Is there a way to just tell my plot code to display the x-axis as "times" class, without having to map the decimals to display values?

View(BedMap)
jesstme
  • 604
  • 2
  • 10
  • 25
  • What are your time values? How would you like to display them? Write a function that converts the time values into the format you want, then see http://stackoverflow.com/questions/11610377/how-do-i-change-the-formatting-of-numbers-on-an-axis-with-ggplot for the way to use it. – Kent Johnson Feb 15 '17 at 20:03
  • When I use View(BedMap) for the current data, as above, the time values show up as times, eg.: DcOrderTime <- c("08:36:00", "09:04:00", "10:20:00", "11:18:00", "09:30:00", "14:58:00", "10:36:00"). I know how to map a random label on top of an axis, but I figured since the data is already in times format, I shouldn't have to do any conversion. I thought there might be a way to just specify that the axis should be displayed in h:m:s format. – jesstme Feb 15 '17 at 20:35
  • 1
    Where is the `times` class defined? – Kent Johnson Feb 15 '17 at 21:15
  • Kent, I think this is my problem! It's from the chron package. I've used it in the past because it's easier to perform calculations on time data. But in this case perhaps I need to start fresh and redefine my times as POSIXlt – jesstme Feb 15 '17 at 21:41

2 Answers2

1

The issue is, I think, linked to the fact that the times class appears to be holding durations rather than times of day (though I cannot actually find the documentation on the class, having never used it before). Because that format is not explicitly handled by ggplot it is being converted to numeric for plotting (you can see the stored numeric values in your output from dput).

While there is likely a better solution involving converting to POSIX or storing the values directly as time of day, you can accomplish your immediate goal by simply multiplying the numeric value (which is fraction of a day) by 24 to get the time. Then, set sensible axis breaks and add labels as desired, like so:

ggplot(BedMap) +
  geom_segment(aes(x = 0, #start of light grey bar, indicates bed occupied & discharge planning has not yet started
                   y = RoomBed, 
                   xend = 24*DcOrderTime, #end of light grey bar
                   yend = RoomBed), 
               color = "Light Grey", 
               size = 6) +
  geom_segment(aes(x = 24*DcOrderTime, #start of dark grey bar, indicates bed still occupied but discharge planning has begun
                   y = RoomBed, 
                   xend = 24*DcTime, #end of dark grey bar, indicates patient has been discharged, bed is unoccupied
                   yend = RoomBed), 
               color = "Dark Grey", 
               size = 6) +
  geom_segment(aes(x = 24*DepartTime, #start of blue bar, indicates new patient has been placed in bed
                   y = RoomBed, 
                   xend = 24, #end of blue bar (set at midnight/end of day)
                   yend = RoomBed), 
               color = "Blue", 
               size = 6) +
  geom_point(aes(x = 24*DecisionTime, 
                 y = RoomBed), 
             color = "black", size = 3) +
  geom_point(aes(x = 24*RequestBedTime, 
                 y = RoomBed), 
             color = "green", size = 3) +
  theme(legend.position = "none") +
  labs(x = "Time", y = "Room-Bed", title = "Daily Bed Map") +
  scale_x_continuous(breaks = seq(0, 24, 3)
                     , labels = sprintf("%02d:00",seq(0, 24, 3))
                     )

Which gives

enter image description here

The builtin in scale_x_time does not appear to work here, and that is part of what leads me to suspsect that the times class holds durations rather than times of day. If you are using this format often, it may be worthwhile to instead write your own transformation/scale function to use repeatedly.

Mark Peterson
  • 9,370
  • 2
  • 25
  • 48
0

Got it! Turns out the answer lies in the fact that class="times" is from the chron package. By adding a simple line at the end of my plot, the display changed simply, without additional mapping. See my original code below, plus additional last line.

ggplot(BedMap) +
    geom_segment(aes(x = 0, #start of light grey bar, indicates bed occupied & discharge planning has not yet started
           y = RoomBed, 
           xend = DcOrderTime, #end of light grey bar
           yend = RoomBed), 
       color = "Light Grey", size = 6) +
    geom_segment(aes(x = DcOrderTime, #start of dark grey bar, indicates bed still occupied but discharge planning has begun
           y = RoomBed, 
           xend = DcTime, #end of dark grey bar, indicates patient has been discharged, bed is unoccupied
           yend = RoomBed), 
           color = "Dark Grey", size = 6) +
    geom_segment(aes(x = DepartTime, #start of blue bar, indicates new patient has been placed in bed
           y = RoomBed, 
           xend = 1, #end of blue bar (set at midnight/end of day)
           yend = RoomBed), 
           color = "Blue", size = 6) +
    geom_point(aes(x = DecisionTime, 
         y = RoomBed), 
     color = "black", size = 3) +
    geom_point(aes(x = RequestBedTime, 
         y = RoomBed), 
     color = "green", size = 3) +
    theme(legend.position = "none") +
    labs(x = "Time", y = "Room-Bed", title = "Daily Bed Map") +
    scale_x_chron(format = "%H:%m", n = 12)
jesstme
  • 604
  • 2
  • 10
  • 25