Search code examples
rshinyggvisposixct

R, problems plotting dates in Shiny and ggvis


I'm a bit new to Shiny and ggvis, and actually have a couple of problems here. First I have data in the format:

            Event.Hour Count    Group
1  2015-10-08 00:00:00  1476      All
2  2015-10-08 01:00:00 22186      All
3  2015-10-08 02:00:00  2958      All
4  2015-10-08 03:00:00  3484      All
5  2015-10-08 04:00:00  4159      All
6  2015-10-08 05:00:00  2960      All
7  2015-10-08 00:00:00   222 Business
8  2015-10-08 01:00:00    26 Business
9  2015-10-08 02:00:00   542 Business
10 2015-10-08 03:00:00    26 Business
11 2015-10-08 04:00:00  4760 Business
12 2015-10-08 05:00:00  4640 Business
13 2015-10-08 00:00:00  1704   System
14 2015-10-08 01:00:00   100   System
15 2015-10-08 02:00:00   122   System
16 2015-10-08 03:00:00    10   System
17 2015-10-08 04:00:00  3339   System
18 2015-10-08 05:00:00  5370   System

The dates were created using lubridate's dmy_hms function:

> class(viz_set$Event.Hour)
[1] "POSIXct" "POSIXt" 

Code to recreate data set:

library(ggvis)
library(dplyr)
library(lubridate)

zz<- "Event.Hour Count    Group
1  2015-10-08-00:00:00  1476      All
2  2015-10-08-01:00:00 22186      All
3  2015-10-08-02:00:00  2958      All
4  2015-10-08-03:00:00  3484      All
5  2015-10-08-04:00:00  4159      All
6  2015-10-08-05:00:00  2960      All
7  2015-10-08-00:00:00   222 Business
8  2015-10-08-01:00:00    26 Business
9  2015-10-08-02:00:00   542 Business
10 2015-10-08-03:00:00    26 Business
11 2015-10-08-04:00:00  4760 Business  
12 2015-10-08-05:00:00  4640 Business
13 2015-10-08-00:00:00  1704   System
14 2015-10-08-01:00:00   100   System
15 2015-10-08-02:00:00   122   System
16 2015-10-08-03:00:00    10   System
17 2015-10-08-04:00:00  3339   System
18 2015-10-08-05:00:00  5370   System"

viz_set<-read.table(text=zz, header = T)

viz_set$Event.Hour <- ymd_hms(viz_set$Event.Hour)

I am then plotting the data as a ggvis object and adding a tooltip to the interactive visual:

getData1 <- function(dat){
  paste(paste("Value:", dat$Count, "<br />"),
        paste("Time:", dat$Event.Hour))
} 

viz_set %>%
  ggvis(~Event.Hour, ~Count, stroke = ~Group) %>% 
  filter(Group %in% eval(input_checkboxgroup(c("All", "Business", "System"), select = "All"))) %>%
  layer_lines(strokeWidth := 2) %>%
  scale_datetime(property = "x", nice = "hour") %>%
  layer_points(opacity = 0, fill = ~Group) %>%
  add_tooltip(getData1, on = "click") %>%
  add_axis("x", subdivide = 5, tick_size_major=10, tick_size_minor = 5, title = "Event.Hour", title_offset = 30) %>%
  add_axis("y", title = "Count", title_offset = 60)

The resulting tooltip displays the dates in Unix epoch format, and I cannot figure out how to get it to simply display as a character.

Inside the getData1 function I've tried:

as.character(dat$Event.Hour)

and

as.POSIXct(dat$Event.Hour, origin = '1970-01-01')

to no avail.

I've also tried adding a new column with the dates as character strings, and used the tooltip on that column instead. Neither have worked.

Second, in the resulting ggvis plot, the X-axis datetimes do not line up with the values. The data appears to start and end several hours before it should:

Here you can see that the X-axis is off by a few hours.

The first data point should start right at the The Oct 08 line, and it should end at 2 pm on the Wed 14.

Any ideas?


Solution

  • It looks like the time zone may be causing the shifted axis. One simple fix is to simply set the time zone in ymd_dms to your system's time zone. Things for me looked reasonable after that.

    (mytz = Sys.timezone())
    [1] "America/Los_Angeles"
    
    viz_set$Event.Hour = ymd_hms(viz_set$Event.Hour, tz = mytz)
    

    In terms of the tooltip, a work around for the time in milliseconds problem would be to simply show the data from the original dataset rather than the dataset coming through ggvis. You can do this by using a key. This involves making an id variable that uniquely represents each row in the original dataset.

    viz_set$id = 1:nrow(viz_set)
    

    Now the tooltip function can look something like the following.

    getData2 = function(dat){
        if(is.null(dat$id)) return(NULL)
        row = viz_set[viz_set$id == dat$id, ]
        paste(paste("Value:", row$Count, "<br />"),
             paste("Time:", as.character(row$Event.Hour)))
    } 
    

    Notice that, unlike the help documentation, the first row of the function involves dat$id and not just dat. When I used dat here, I would sometimes get blank tooltip info showing up if I mistakenly clicked on the line instead of the point. My alternative seems to solve that problem.

    Now just add key := ~id to layer_points to get the tooltip values popping up from the actual dataset.

    viz_set %>%
        ggvis(~Event.Hour, ~Count, stroke = ~Group) %>% 
        filter(Group %in% eval(input_checkboxgroup(c("All", "Business", "System"), select = "All"))) %>%
        layer_lines(strokeWidth := 2) %>%
        scale_datetime(property = "x", nice = "hour") %>%
        layer_points(opacity := 0, fill = ~Group, key := ~id) %>%
        add_tooltip(getData2, on = "click") %>%
        add_axis("x", subdivide = 5, tick_size_major=10, tick_size_minor = 5, title = "Event.Hour", title_offset = 30) %>%
        add_axis("y", title = "Count", title_offset = 60)