Note: If you’re viewing the HTML version of this document generated with knitr, the examples will have their interactive features disabled. You’ll need to run the code in R to see and use the interactive controls.
Ggvis interactivity is built on top of Shiny’s reactive programming model. It’s possible to use ggvis without understanding how Shiny works, but you’ll be limited to relatively simple interactions. The first part of this vignette describes basic interactive controls, which provide a quick and easy way to add basic interactivity to a plot. They are not very flexible, but they cover the most common interactive needs and you don’t need to know anything about Shiny to use them.
The second part of this vignette shows you how to embedding a ggvis in a Shiny app. This gives you complete freedom to make any component of the plot interactive, to display multiple plots on one page, and to freely arrange controls. The downside is that you’ll need more code, and you’ll need at least a basic understanding of Shiny. If you’re not already familiar with how Shiny works, I recommend that you first read through the Shiny tutorial
A plot with basic interactive controls looks very similar to a static plot. You just replace constant values with functions that produce interactive controls like input_slider()
:
}
mtcars %>%
ggvis(~wt, ~mpg) %>%
layer_smooths(span = input_slider(0.5, 1, value = 1)) %>%
layer_points(size := input_slider(100, 1000, value = 100))
As well as input_slider()
, which produces a slider (or a double-ended range slider), there are a number of other interactive controls:
input_checkbox()
: a check-boxinput_checkboxgroup()
: a group of check boxesinput_numeric()
: a spin boxinput_radiobuttons()
: pick one from a set optionsinput_select()
: create a drop-down text boxinput_text()
: arbitrary text inputNote that all interactive inputs start with input_
so that you can always use tab completion to remind you of the options.
Here is an example of a plot that uses both a slider and a select box:
mtcars %>% ggvis(x = ~wt) %>%
layer_densities(
adjust = input_slider(.1, 2, value = 1, step = .1, label = "Bandwidth adjustment"),
kernel = input_select(
c("Gaussian" = "gaussian",
"Epanechnikov" = "epanechnikov",
"Rectangular" = "rectangular",
"Triangular" = "triangular",
"Biweight" = "biweight",
"Cosine" = "cosine",
"Optcosine" = "optcosine"),
label = "Kernel")
)
The arguments differ slightly depending on the type of input, and are documented in the individual function documentation. All input sliders share three common arguments:
label
: an informative text label displayed next to the control
id
: a unique identifier for the control - this is randomly assigned and you should only need to override in exceptional circumstances.
map
: a function that enables you to remap the output of the input to something appropriate for your graphic.
map
is the most commonly argument used as it allows you to translate the value recieved from the input to something that’s meaningful for your plot. For example, many parameters of statistical models are best expressed on a log scale. You can use map
in conjunction with an slider to make multiple orders of magnitude easily accessible from a single slider.
input_slider(-5, 5, label = "lambda", map = function(x) 10 ^ x)
There are two ways to have an interactive input control multiple settings on the plot.
Use the regular property inheritance structure:
mtcars %>%
ggvis(~wt, ~mpg, size := input_slider(10, 1000)) %>%
layer_points(fill := "red") %>%
layer_points(stroke := "black", fill := NA)
Create the input and assign it to a variable:
slider <- input_slider(10, 1000)
mtcars %>% ggvis(~wt, ~mpg) %>%
layer_points(fill := "red", size := slider) %>%
layer_points(stroke := "black", fill := NA, size := slider)
This is a little more typing, but is more flexible. Both of them will result in the below:
Compare the following two plots. In the first plot, one slider is created and used for both layers - it controls the size of both the red and the black points. In the second plot, you get two independent sliders which allow you to control the size of the red and black points independently.
slider <- input_slider(10, 1000)
mtcars %>% ggvis(~wt, ~mpg) %>%
layer_points(size := slider) %>%
layer_points(fill := "red", opacity := 0.5, size := slider)
mtcars %>% ggvis(~wt, ~mpg) %>%
layer_points(size := input_slider(100, 1000, label = "black")) %>%
layer_points(fill := "red", size := input_slider(100, 1000, label = "red"))
When you map a slider to a property, you have four basic options:
If you just assign the input in props()
, like props(size = input_slider())
, you’ll get a constant, unscaled property. To gain more control you can use prop()
: props(prop("size", input_slider()))
.
You’ll need to do this if you want to:
select a variable to plot based on a dropdown: prop(x = input_select(c("disp", "wt")), constant = FALSE)
annotate the plot in the data space: prop(x = input_slider(min(mpg$wt), max(mpg$wt)), scale = TRUE)
You can read more about these options in the properties and scales vignette.
Currently, interactive inputs can only be used in two places:
layer_smooths(span = input_slider(0, 1))
props(size = input_slider(10, 1000))
This means that interactive inputs can only modify the data, not the underlying plot specification. In other words, with only basic interactivity there’s no way to add or remove layers, or switch between different datasets. This is a reasonable limitation because if you’re doing exploration you can always create a new ggvis with R code, or if you’re polishing a plot for presentation, you can embed it in a Shiny app and gain full control over the plot.
If you’re familiar with Shiny, you’ll notice that these functions have very similar equivalents: sliderInput()
, selectInput()
and so on. There are two main differences:
the argument order has been tweaked so that you can create a basic control with minimal arguments. The label
is optional because if you’re creating a plot for yourself, you usually remember what the controls do; and each control is assigned a random id
so you don’t need to think one up.
interactive input are not necessarily created in a reactive context, so they can not return reactives. Instead, they return delayed reactives, which are activated and connected together when the plot is displayed.
If you know how to create a Shiny app already, adding a ggvis plot is easy. In server.r
, create a ggvis object, and call bind_shiny()
. When called in a pipe, the arguments are the names of the plot and control placeholders.
# A reactive expression wrapper for input$size
input_size <- reactive(input$size)
mtcars %>%
ggvis(~disp, ~mpg, size := input_size) %>%
layer_points() %>%
bind_shiny("ggvis", "ggvis_ui")
Create ui.r
as usual, using ggvisOutput()
to place the ggvis plot on the page.
shinyUI(pageWithSidebar(
sidebarPanel(
sliderInput("size", "Area", 10, 1000)
),
mainPanel(
uiOutput("ggvis_ui"),
ggvisOutput("ggvis")
)
))
There are a couple of examples in the demo/apps
directory.