Robert Kingston Robert Kingston - 17 days ago 9
R Question

Interactive datetime input on ggvis plots

Let's say you want to make an interactive

ggvis
plot with datetime data on the X axis: i.e. you want to be able to zoom in on specific times in the plot.

Is this a) possible b) have any workaround or c) better solved by another package?

Take this example data and plot for example:

library(ggvis)

df <- data.frame(time = rep(as.POSIXct("2013-10-10")+(1:100)*60^2,2),
treatment = c(rep("a",100),rep("b",100)), rate = rnorm(200,0.3,.01),
upper = rnorm(200,0.4,.01), lower = rnorm(200,0.2,.01))

df %>%
group_by(treatment) %>%
ggvis(~time,~rate,stroke=~treatment) %>%
layer_ribbons(y=~upper,y2=~lower,fill=~treatment,opacity:=0.2) %>%
layer_lines() %>%
scale_datetime("x", nice = "hour")

Answer

I think this would be better solved by another package since ggvis doesn't handle this task very elegantly. As an alternative, we could use dygraphs and dyRangeSelector()

First, we reshape the data in a wide format:

library(tidyr)
x <- df %>%
  gather(key, value, -(time:treatment)) %>%
  unite(t, treatment, key) %>%
  spread(t, value) 

This will give you:

> head(x)
#                 time   a_lower    a_rate   a_upper   b_lower    b_rate   b_upper
#1 2013-10-10 01:00:00 0.1988794 0.2903746 0.4031802 0.2089536 0.2851947 0.3850488
#2 2013-10-10 02:00:00 0.1997263 0.3012017 0.4030821 0.1935425 0.3103502 0.4047333
#3 2013-10-10 03:00:00 0.1999701 0.2908635 0.3992913 0.1996834 0.2978400 0.3904020
#4 2013-10-10 04:00:00 0.2045941 0.2947663 0.4140974 0.2184334 0.2969331 0.3979316
#5 2013-10-10 05:00:00 0.1801551 0.3167674 0.4180428 0.1842388 0.2974034 0.3987412
#6 2013-10-10 06:00:00 0.1986528 0.2946848 0.3887903 0.1992093 0.3093617 0.4051101

Then, we create an xts object:

library(xts)
y <- xts(x[-1], order.by = x$time)  

Finally, we generate the plot.

library(dygraphs)
dygraph(y, main = "A nice dygraph with range selector") %>%
  dyAxis("x", drawGrid = FALSE) %>%
  dySeries(c("a_lower", "a_rate", "a_upper"), label = "a") %>%
  dySeries(c("b_lower", "b_rate", "b_upper"), label = "b") %>%
  dyRangeSelector()

You can zoom either using mouse selection or the range selector

enter image description here