Search code examples
rshinyggvis

ggvis plot disappears with tooltip and checkBoxInput Shiny


I have a problem with using tooltip in ggvis in my Shiny app. I would like to use additional info about dot point in ggvis, that's why I create function which need id variable:

add_info <- function(x) {
  if(is.null(x)) return(NULL)
  if (is.null(x$id)) return(NULL)
  df2<- isolate(data)
  df <- df2[df2$id == x$id, ]
  paste0(df$info,
         df$number)
}

The problem starts when I work with checkBox buttons in Shiny app i.e. when I unclick all buttons, error comes up:

Error in eval(substitute(expr), envir, enclos) : 
  wrong result size (2), expected 0 or 1 

I know that is because of my filter condition which excluded all data. But in that case, I want to see an empty plot when I unclick all checkBox options ( like as in Line plot below). How to do it?

ui.R

library(shiny)

shinyUI(fluidPage(

  titlePanel(""),

  sidebarLayout(
    sidebarPanel(
      wellPanel(checkboxGroupInput("variable",label = "",
                         choices = list("a","b","c","d"),
                         selected = c("a"))),
      br(),br(),br(),br(),br(),br(),br(),br(),

      wellPanel(checkboxGroupInput("variable2",label = "",
                         choices = list("a","b","c","d"),
                         selected = c("a")))      
    ),

    mainPanel(
      ggvisOutput("scatter_plot"),
      ggvisOutput("line_plot")
    )
  )
))

server.R

library(shiny)

shinyServer(function(input, output) {

  dataset <- reactive({
    df <- df1 %>%
      filter(name %in% input$variable)
    df
  })

    data <- reactive({
      dataset() %>%
        mutate(id = 1:n())
    })

  vis2 <- reactive({
    add_info <- function(x) {
      if(is.null(x)) return(NULL)
      if (is.null(x$id)) return(NULL)
      df2 <- isolate(data())
      df <- df2[df2$id == x$id, ]
      paste0(df$info,"<br>",
             df$number)
    }
    data() %>%
      ggvis(~number2, ~number, fill = ~name) %>%
      layer_points(size := 100,
                   size.hover := 240,
                   key := ~id) %>%
      add_tooltip(add_info,"hover")
  })
  vis2 %>% bind_shiny("scatter_plot")

  # LinePlot  
dataset_line <- reactive({
  df_line <- df1 %>%
    filter(name %in% input$variable2)
})

    vis <- reactive({

      dataset_line() %>%
        ggvis(~number2, ~number, stroke = ~name) %>%
        layer_lines()

    })
    vis %>% bind_shiny("line_plot")

})

global.R

df1 <- data.frame(name = rep(letters[1:4],each = 5), number = df1_number, number2 = df1_number2,
                  info = "info")

df1_number <-sample(seq(1,20,0.01),20,replace = T)
df1_number2 <-sample(seq(1,5,0.01),20,replace = T)

Solution

  • Your error is actually coming from your dplyr mutate call. That error is returned when you try to count with n() when there are no rows (i.e. an empty dataset). This prevents it from creating the id variable and causes your downstream problems with ggvis. To fix this, all you need to do is change 1:n() to row_number() (thanks to @docendodiscimus for the suggestion). To consolidate, remove the dataset statement and just use the following:

    data <- reactive({
              df1 %>%
                filter(name %in% input$variable) %>%
                mutate(id = row_number())
          })
    

    that should fix your problem.

    Here is a working gist as an example.

    runGist("https://gist.github.com/cdeterman/806f51c254c523f88f01")