Search code examples
rshinyggvis

Making ggvis plots reactive with shiny


I have the following plot and I wish to make it interactive. More specifically, I'd like a slider for maximum supply to range between 60 and 120. I've read through the shiny and ggvis documentation and I can't get it to work. I've included an attempt below.

library(ggvis)
library(dplyr)
library(tidyr)

maximum_supply = input$maximum_supply

supply.function = function(supply)
  60 - 60/maximum_supply * supply

data_frame(quantity = 0:maximum_supply) %>%
  mutate(price = supply.function(quantity)) %>%
  ggvis(~quantity, ~price) %>%
  layer_lines()

shiny.R

library(shiny)
library(ggvis)
library(dplyr)

shinyServer(function(input, output) {

  reactive({ 
    maximum_supply = 120

    supply.function = function(supply)
      60 - 60/maximum_supply * supply

    data_frame(quantity = 0:maximum_supply) %>%
      mutate(price = supply.function(quantity)) %>%
      ggvis(~quantity, ~price) %>%
      layer_lines() %>%
      bind_shiny("ggvis", "ggvis_ui")
  })
})

ui.R

library(shiny)
library(ggvis)
library(dplyr)

shinyUI(fluidPage(

  titlePanel("Example"),

  sidebarLayout(
    sidebarPanel(
      sliderInput("maximum_supply",
                  "Maximum Supply",
                  min = 60,
                  max = 120,
                  value = 90),
    ),

    mainPanel(
      uiOutput("ggvis_ui"),
      ggvisOutput("ggvis")
    )
  )
))

Solution

  • Making the data that you pass to ggvis reactive is the key here, since you want to be able to subset it in response to user input. Also, the maximum_supply is part of input and can be accessed via input$maximum_supply in the supply function and the reactive data.

    library(ggvis)
    library(shiny)
    library(dplyr)
    
    shinyApp(
        shinyUI(fluidPage(
            titlePanel("Example"),
            sidebarLayout(
                sidebarPanel(
                    sliderInput("maximum_supply",
                                "Maximum Supply",
                                min = 60,
                                max = 120,
                                value = 90),
                    uiOutput("ggvis_ui")
                ),
                mainPanel(
                    ggvisOutput("ggvis")
                )
            )
        )),
        shinyServer(function(input, output) {
            supply.function <- function(supply) {
                60 - 60/input$maximum_supply* supply
            }
    
            dat <- reactive({ data.frame( quantity = 0:input$maximum_supply ) })
    
            dat %>%
              mutate(price = supply.function(quantity)) %>%
              ggvis(~quantity, ~price) %>%
              layer_lines() %>%
              bind_shiny("ggvis", "ggvis_ui")
        })
    )