Search code examples
rshinyr-plotly

Display Plotly graph in R Shiny


I am following the kmeans tutorial in the R Shiny Gallery and wanted to modify to use three variables and plot in a plotly 3D scatter. There are no errors, but the graph is not displaying. This seems like it should work...what am I doing wrong?

data <- iris %>% select(-Species)

# this works
# data %>%
#   plot_ly(x = ~Petal.Length, y = ~Petal.Width, z = ~Sepal.Length) %>%
#   add_markers()

server = function(input, output, session) {

  # Combine the selected variables into a new data frame
  selectedData <- reactive({
    data[, c(input$xcol, input$ycol, input$zcol)]
  })

  clusters <- reactive({
    kmeans(selectedData(), input$clusters)
  })

  output$plot1 <- renderPlotly({
    selectedData() %>%
      plot_ly(x = ~input$xcol, y = ~input$ycol, z = ~input$zcol) %>%
      add_markers()
  })

}

ui <- 

  pageWithSidebar(
    headerPanel('Iris'),
    sidebarPanel(
      selectInput('xcol', 'X Variable', names(data)),
      selectInput('ycol', 'Y Variable', names(data)),
      selectInput('zcol', 'Z Variable', names(data)),
      numericInput('clusters', 'Cluster count', value = 3, step = .5, min = 1, max = 10)
    ),
    mainPanel(
      plotOutput('plot1')
    )
  )

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

Solution

  • To correctly render a plotly output in Shiny you need to use plotlyOutput instead of plotOutput.

    With respect to subsetting dataframes with user selected input, I tend to first store the output of a reactive function, and then subset as I would subset any other dataframe. In that way, the reactive function is called only once.

    In any case, a good resource to better understand shiny is https://mastering-shiny.org/

    Hope this helped :)

    library(shiny)
    library(plotly)
    
    data <- iris %>% select(-Species)
    
    server = function(input, output, session) {
    
    # I Combined the selected variables into a new data frame
    # and added a new column with the cluster id assignated to each observation
    
    selectedData <- reactive({
      res <- data[, c(input$xcol, input$ycol, input$zcol)]
      k <- kmeans(res, input$clusters)
      clusters <- k$cluster
      res$clusters <- clusters
      res
    })
    
    output$plot1 <- renderPlotly({
      df <- selectedData()
      plot_ly(x = df[, input$xcol], y = df[, input$ycol], z = df[, input$zcol],
            color = df$clusters) %>%
      add_markers()
    })
    
    }
    
    ui <- pageWithSidebar(
     headerPanel('Iris'),
     sidebarPanel(
      selectInput('xcol', 'X Variable', names(data), selected = names(data)[1]),
      selectInput('ycol', 'Y Variable', names(data), selected = names(data)[2]),
      selectInput('zcol', 'Z Variable', names(data), selected = names(data)[3]),
      numericInput('clusters', 'Cluster count', value = 3, step = 1, min = 1, max = 10)
     ),
     mainPanel(
      plotlyOutput('plot1')
     )
    )
    
    # Run the application 
    shinyApp(ui = ui, server = server)