Search code examples
rshinyplotly

plotly scatterplot values shown in widget in shiny but I cannot see the points on the graph?


I am trying to create an interactive graph from a dataframe with some NA and string values. Would these values prevent a scatterplot? The string values are easy to remove as I can just remove the column with select(-column) but I am struggling with the NA values. I followed the code from this example (https://community.plotly.com/t/incorporate-a-plotly-graph-into-a-shiny-app/5329/2) but it does not work when I try to use my own data set.

I tried to use the plot_ly code to create an interactive scatterplot. I used the shiny outline (ui, server, shinyApp). I expected to see the scatterplot show the data but it would not.

library(shiny)
library(plotly)
library(tibble)
library(tidyverse)
library(tidyr)
library(readr)
library(dplyr)
library(ggplot2)

# set working directory
setwd("~/BDSWD")

#add data
gmclean <- read_csv("gapminder_clean.csv")

#remove certain columns
gmcut <- gmclean %>%
  select(-Year, -continent, -pop, -`Country Name`)

#no NA values
gmna <- replace(gmcut, is.na(gmcut), 0)

# Define UI ----
ui <- fluidPage(
  column(3,offset = 4, titlePanel("Explor Gapminder Data with Shiny")),
  headerPanel('Variables'),
  mainPanel(
    plotlyOutput('plot')
  ),
  sidebarPanel(
    #variable selection for x-axis
    selectInput(inputId ='xvrbl', #The input slot that will be used to access the value.
                label = 'X-Axis Variable', #Display label for the control, or NULL for no label.
                choices = colnames(gmcut), #List of values to select from
                selected = ""
                ),
    #variable selection for y-axis
    selectInput(inputId ='yvrbl', #The input slot that will be used to access the value.
                label = 'Y-Axis Variable', #Display label for the control, or NULL for no label.
                choices = colnames(gmcut), #List of values to select from
    )
  )
)

server <- function(input, output) {

  x <- reactive({
    gmcut[,input$xvrbl]
  })

  y <- reactive({
    gmcut[,input$yvrbl]
  })


  output$plot <- renderPlotly(
    plot1 <- plot_ly(
      x = x(),
      y = y(),
      type = 'scatter',
      mode = 'markers')
  )

}

# Run the app
shinyApp(ui = ui, server = server)

Solution

  • The issue is (most likely) that gmcut is a tibble. When you do e.g. gmcut[,input$xvrbl] the result is a tibble too instead of a vector (This is one of the differences between a data.frame and a tibble. In case of a data.frame the result would be a vector).

    Hence, as plot_ly expects vectors you get an "empty" plot as you are passing tibbles to x and y.

    To fix that use gmcut[[input$xvrbl]] instead or explicitly drop the dimensions using gmcut[, input$xvrbl, drop = TRUE].

    Using the gapminder::gapminder dataset as example data:

    library(shiny)
    library(plotly)
    library(tidyverse)
    
    # add data
    gmclean <- gapminder::gapminder |>
      rename(Year = year, "Country Name" = country)
    
    # remove certain columns
    gmcut <- gmclean %>%
      select(-Year, -continent, -pop, -`Country Name`)
    
    # no NA values
    gmna <- replace(gmcut, is.na(gmcut), 0)
    
    # Define UI ----
    ui <- fluidPage(
      column(3, offset = 4, titlePanel("Explor Gapminder Data with Shiny")),
      headerPanel("Variables"),
      mainPanel(
        plotlyOutput("plot")
      ),
      sidebarPanel(
        # variable selection for x-axis
        selectInput(
          inputId = "xvrbl", # The input slot that will be used to access the value.
          label = "X-Axis Variable", # Display label for the control, or NULL for no label.
          choices = colnames(gmcut), # List of values to select from
          selected = ""
        ),
        # variable selection for y-axis
        selectInput(
          inputId = "yvrbl", # The input slot that will be used to access the value.
          label = "Y-Axis Variable", # Display label for the control, or NULL for no label.
          choices = colnames(gmcut), # List of values to select from
        )
      )
    )
    
    server <- function(input, output) {
      x <- reactive({
        gmcut[[input$xvrbl]] ## or gmcut[, input$xvrbl, drop = TRUE]
      })
    
      y <- reactive({
        gmcut[[input$yvrbl]]
      })
    
    
      output$plot <- renderPlotly({
        plot1 <- plot_ly(
          x = x(),
          y = y(),
          type = "scatter",
          mode = "markers"
        )
      })
    }
    
    # Run the app
    shinyApp(ui = ui, server = server)
    #> 
    #> Listening on http://127.0.0.1:7126