Does anyone know if it is possible to change the variables for the x and y axis interactively with ggvis? I can change the size of the data points, their position and opacity, but I can't work out if its possible to allow the user to select a variable from a dropdown that will become the data for the x/y axis.
-
Please [read this](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). – nrussell Jul 19 '14 at 14:55
5 Answers
You can do that like this:
library('ggvis');
mtcars %>% ggvis(~mpg, input_select(names(mtcars), map = as.name)) %>% layer_lines()
# or specify by hand
mtcars %>% ggvis(~mpg, input_select(c('wt', 'disp'), map = as.name)) %>% layer_lines()
(the key is to use map and a suitable function, in this case as.name() does it but you can create your own if you have special needs)
See documentation for input_select: http://www.rdocumentation.org/packages/ggvis/functions/input_select
The documentation for interactivity referenced in the answer describing the shiny solution (well, I need reputation points to post more than 2 links so I can't do it but the link is given in there!) indicates that this is possible (contrary to what that answer states) but the syntax provided there doesn't work:
prop(x = input_select(c("disp", "wt")), constant = FALSE)
# which is to be used with props:
props(prop(x = input_select(c("disp", "wt")), constant = FALSE))
However there are hints to the use of as.name (http://ggvis.rstudio.com/properties-scales.html):
var <- "mpg"
prop("x", as.name(var))

- 191
- 3
-
1alternatively, convert columns into rows and have & plot them together w/ different colors (this may not be applicable to some cases, eg. when there are many columns), here I combined vs and am into one numeric column, val, and add another column, new.field that keeps a record of which type the value under val is. Then I use fill to have separate colors for each type: df1 <- rbind(cbind(new.field='vs', val=NA, mtcars), cbind(new.field='am', val=NA, mtcars)); df1$val <- ifelse(df1$new.field=='vs', df1$vs, df1$am); df1 %>% ggvis(~mpg, ~val, fill=~factor(new.field)) %>% layer_points() – Adrian Chira Sep 09 '14 at 18:56
-
The ggvis
package was designed to be used in conjunction with dplyr
, e.g. to summarise data. The dplyr
package also re-exports the magrittr
pipe operator (%>%
, see README.md), which makes working with ggvis
' implementation of The Grammar of Graphics particularly intuitive (see also this article by the author of these packages, Hadley Wickham).
Below I'll illustrate how to use the input_select()
function to change the x
of a model and leave the y
constant.
First we need to load the two required libraries:
library(dplyr)
library(ggvis)
Now we can plot a data.frame
(I'm using the build-in pre-loaded iris
):
iris %>%
ggvis(x = input_select(c('Petal.Width', 'Sepal.Length'), map = as.name)) %>%
layer_points(y = ~Petal.Length, fill = ~Species)
The output is:
using the input_select
this can be changed to:
If you prefer not to use dplyr
/ magrittr
it would look like this:
p <- ggvis(iris, x = input_select(c('Petal.Width', 'Sepal.Length'), map = as.name))
layer_points(p, y = ~Petal.Length, fill=~Species)

- 2,802
- 1
- 24
- 50
-
At the time this was the closest thing, now the answer below is better. I still don't see why you would vote it down – Bastiaan Quast May 19 '15 at 09:14
You can't do this directly in ggvis
currently (v0.3). From the documentation:
Currently, interactive inputs can only be used in two places:
1. as arguments to transforms: layer_smooths(span = input_slider(0, 1))
2. as properties: 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.
So the solution is to use shiny
and to have inputs for the variables and reactively define the data-set. Here's your server.R:
library(shiny);library(ggvis)
shinyServer(function(input, output) {
plotData <- reactive({
df <- iris[,c("Sepal.Width",input$yVariable,"Species")]
names(df) <- c("x","y","fill")
df
})
reactive({ plotData() %>% ggvis(x=~x,y=~y,fill=~fill) %>%
layer_points() %>%
add_axis("x", title = "Sepal.Width") %>%
add_axis("y", title = input$yVariable) %>%
add_legend("fill", title = "Species")
}) %>% bind_shiny("ggvisPlot")
})
and your ui.R:
library(shiny);library(ggvis)
shinyUI(fluidPage(
titlePanel("ggvis with changing data-set"),
sidebarLayout(
sidebarPanel(
selectInput("yVariable", "Y Variable:",
c("Petal.Width" = "Petal.Width",
"Petal.Length" = "Petal.Length"),selected = "Petal.Width")
),
mainPanel(
ggvisOutput("ggvisPlot")
)
)
))

- 856
- 1
- 7
- 23
You could also build the plot into a shiny reactive function that swaps the axes. There may be a flash when ggvis redraws the plot, but it will have the effect you're looking for.
This modifies the code from ideamotor, above; I also altered it to use the reactive function rather than reactive data as the input to ggvis, which allows ggvis to ... oh, just try it, you'll see:
library(shiny);library(ggvis)
shinyServer(function(input, output) {
plotData <- reactive({
df <- iris[,c("Sepal.Width",input$yVariable,"Species")]
names(df) <- c("x","y","fill")
df
})
reactive({
plt <- **plotData** %>% ggvis(fill=~fill) %>%
add_legend("fill", title = "Species")
if (**input$someCheckBox**) {
plt <- plt %>%
layer_points(x = ~x, y = ~y) %>%
add_axis("x", title = "Sepal.Width") %>%
add_axis("y", title = input$yVariable)
} else {
plt <- plt %>%
layer_points(x = ~y, y = ~x) %>%
add_axis("y", title = "Sepal.Width") %>%
add_axis("x", title = input$yVariable)
}
plt
}) %>% bind_shiny("ggvisPlot")
})

- 1,274
- 1
- 13
- 26
Yes. You could do as follows:
library(ggvis)
mtcars %>%
ggvis(x = ~mpg, y = input_select(label = "Choose what to plot:",
choices = names(mtcars),
selected = "cyl",
map = as.name)) %>%
layer_points()
If you want to select both variable just do the same for x.

- 467
- 3
- 10