ggvis
is a simple way to get interactive plots
Like ggplot
this expects a dataframe/tibble as an input
Some differences:
%>%
instead of +
aes(color=group)
, write color = ~group
color:=clr_val
color
becomes stroke
alpha
becomes opacity
library('tidyverse')
library('shiny')
library('ggvis')
load('HomeValues.RData')
HomeValues$qtr <- as.double(HomeValues$qtr)
Attaching package: ‘ggvis’ The following object is masked from ‘package:ggplot2’: resolution
plt<- ggvis(HomeValues,x=~qtr,y=~Home.Value,stroke=~State) %>%
layer_lines(); plt
plt <- plt %>% hide_legend('stroke'); plt
plt %>% layer_points(); plt
plt %>% layer_points(size=1, fillOpacity=.1) # Bug!
ggvis
uses both =
and :=
for assignments
Use =
to map a variable to a property
~
to refer to a column of a dataframeUse :=
when we set a property based on a value
plt %>% layer_points(size:=1, fillOpacity:=.1)
In the end, set properties using = ~column
or := value
So why use ggvis
instead of ggplot
?
plt %>% layer_points(size:=input_slider(.1,50,1),
fill =~ State, fillOpacity:=.5) %>%
hide_legend('fill')
plt %>% add_tooltip(function(x)
{paste(x$State,":",x$Home.Value)},'hover')
add_tooltip
needs a function to read value and return a string
State
,Value
For lines, add_tooltip
only prints first value (http://stackoverflow.com/questions/28540504/mouse-hover-in-layer-lines-ggvis-r)
layer_points()
for all valuesplt <- plt %>% layer_points(size:=input_slider(0,5))
plt %>% add_tooltip(function(x)
{paste(x$State,":",x$Home.Value)},'hover')
mtcars %>% ggvis(~wt, ~mpg) %>% layer_points() %>%
layer_smooths(span = input_slider(0.2, 1))
plt <-ggvis(HomeValues x=~qtr,y=~Home.Value,stroke=~State) %>%
layer_smooths(span:=input_slider(0,5)) %>%
hide_legend('stroke')
Error in parse(text = x, srcfile = src): <text>:1:24: unexpected symbol 1: plt <-ggvis(HomeValues x ^ Traceback:
Error because ggvis
doesn't do grouping for you (unlike ggplot
)
plt <- HomeValues %>% group_by(State) %>%
ggvis(x=~qtr,y=~Home.Value, stroke=~State) %>%
layer_smooths(span=input_slider(0,2,step=.1)) %>%
hide_legend('stroke')
ggvis(HomeValues) %>% layer_histograms(x=~Home.Value)
ggvis(HomeValues) %>%
layer_histograms(x=~Home.Value,
width=input_slider(min=1000,max=100000))
ggvis(HomeValues) %>%
layer_histograms(x=~Home.Value, fill.hover:='red',
width=input_slider(min=10^3,max=10^5))
plt<- ggvis(HomeValues,x=~qtr,y=~Home.Value,stroke=~State) %>%
layer_lines(stroke.hover:='black') %>%
hide_legend('stroke')
plt %>% add_tooltip(function(x)
{paste(x$State,":",x$Home.Value)},'hover')
tidyverse
commands can be overloaded for use with ggvis
:
plt <- HomeValues %>% group_by(State) %>%
ggvis(x=~qtr,y=~Home.Value, stroke=~State) %>%
filter(State %in% eval(input_select(choices =
unique(as.character(HomeValues$State)),
multiple=TRUE, label='States list'))) %>%
layer_lines(strokeWidth:=2)
Note the eval
, this is because of we are calling input_select
inside filter
http://stackoverflow.com/questions/25891020/dynamic-filtering-with-input-select-using-ggvis-in-r
library('ggplot2');library('maps')
my_state_map <- map_data('state');
my_state_map$region <- tolower(my_state_map$region)
get_ab <- function(x) state.abb[x == tolower(state.name)]
get_house_pr <- function(st,yr) {
HomeValues[HomeValues$State==st & HomeValues$qtr==yr,2] }
state.name[51]<-"district of columbia"; state.abb[51]<-"DC"
# apply get_ab to each row of my_state_map
my_state_map$region <- purrr::map_chr(my_state_map$region,
get_ab)
get_yr_pr <- function(yr) { # Function to get vector of prices
pr <- my_state_map$pr # of yr
for(st in state.abb)
pr[my_state_map$region == st] <- get_house_pr(st,floor(yr))
return(pr)
}
Attaching package: ‘maps’ The following object is masked from ‘package:purrr’: map
my_state_map %>% ggvis(~long, ~lat) %>%
mutate(pr = eval(input_slider(1976,2013,
map= function(x) get_yr_pr(x)))) %>%
group_by(region) %>% layer_paths(fill=~pr) %>%
hide_axis("x") %>% hide_axis("y") %>%
set_options(duration=0,width=960,height=600,keep_aspect=TRUE) %>%
hide_legend('fill') %>% hide_legend('stroke') %>%
add_tooltip(function(x) {
paste(isolate(x$curr),":",x$region,":",x$pr)},'hover') %>%
scale_numeric("fill", range = c("yellow","red"))
ggvis
is also compatible with reactive programing
This is a programming paradigm imported from shiny (https://shiny.rstudio.com/articles/reactivity-overview.html)
At a high level a reactive source feeds inputs to reactive end-points
ggvis
automatically updates when a reactive input changes
#https://r2014-mtp.sciencesconf.org/file/92631
#library(shiny)
dat <- data.frame(time=1:10, value=runif(10))
# Create a reactive that returns a data frame, adding a new
# row every 2 seconds
ddat <- reactive({
invalidateLater(500, NULL) # wait of 2 seconds
dat$time <<- c(dat$time[-1], dat$time[length(dat$time)] + 1)
dat$value <<- c(dat$value[-1], runif(1))
dat
})
ddat %>% ggvis(x = ~time, y = ~value, key := ~time) %>%
layer_points() %>% layer_paths()