Dynamic Visualization

Hello everyone,

I am trying to visualize cluster results in a shiny app. As a mock example I am using the iris dataset and attach three columns of artificial cluster results. Now I wantthe user to select as many variables as she likes and for each variable selected, I want to display the boxplots for each cluster.

Now my issue: The boxplots are always updated to the last variable that is entered and I cannot figure out why. I select the first variable, one boxplot for each cluster is created. Perfect! I select one more variable and a second set of boxplots is created for the second variable. However, the first set of boxplots is also updated, which I don't want.

Please find some example code below:

#cluster visu#
library(shiny)
library(shinydashboard)
library(ggplot2)

results <- data.frame(iris, mechanism1 = sample(1:3, 150, replace = TRUE), mechanism2 = sample(1:3, 150, replace = TRUE), mechanism3 = sample(1:3, 150, replace = TRUE))


ui <- dashboardPage(
  dashboardHeader(title = "Clustering"),
  dashboardSidebar(
    sidebarMenu(
      menuItem("Graphical Output", tabName = "graph_output", icon = icon("dashboard"))
  )),
  dashboardBody(
    tabItems(
      tabItem(tabName = "graph_output",
              fluidRow(
                box(
                  width = 12,
                  uiOutput("select_res_graph")
                )
              ),
              fluidRow(
                box(
                  title = "Box Plots",
                  width = 12,
                  uiOutput(outputId = "plot_box")
                )
              )
      )
    )
  )
)


server <- function(input, output, session) {
  output$select_res_graph <- renderUI({list(selectizeInput(inputId = "select_result_graph",
                                                           label = "Choose Mechanism",
                                                           choices = colnames(results)[-c(1, 2, 3, 4, 5)]),
                                            selectizeInput(inputId = "select_var",
                                                           label = "Choose Variables",
                                                           choices = colnames(results)[1:4],
                                                           multiple = TRUE)
  )
  })
  createboxPlots <- reactive ({ 
    for (i in 1:length(input$select_var)) {
      output[[paste0("plot", i)]] <- renderPlot({
        ggplot(results, aes(x = as.factor(get(input$select_result_graph)), y = get(input$select_var[i]), fill=factor(as.factor(input$select_result_graph)))) + geom_boxplot() + theme(legend.position = "none")
      })
    }
  })
  
  
  output$plot_box <- renderUI({
    if (is.null(input$select_var))
      return(NULL)
    createboxPlots()
    plot_output_list <- lapply(1:length(input$select_var), function(i) {
      plotOutput(paste0("plot", i))
    })
    do.call(tagList, plot_output_list)
  })
}

shinyApp(ui, server)

Any help will be much appreciated!

Hi there,

Your issue was a real challenge, but I managed to fix it in the end:

#cluster visu#
library(shiny)
library(shinydashboard)
library(ggplot2)

results <- data.frame(iris, mechanism1 = sample(1:3, 150, replace = TRUE), mechanism2 = sample(1:3, 150, replace = TRUE), mechanism3 = sample(1:3, 150, replace = TRUE))


ui <- dashboardPage(
    dashboardHeader(title = "Clustering"),
    dashboardSidebar(
        sidebarMenu(
            menuItem("Graphical Output", tabName = "graph_output", icon = icon("dashboard"))
        )),
    dashboardBody(
        tabItems(
            tabItem(tabName = "graph_output",
                    fluidRow(
                        box(
                            width = 12,
                            uiOutput("select_res_graph")
                        )
                    ),
                    fluidRow(
                        box(
                            title = "Box Plots",
                            width = 12,
                            uiOutput(outputId = "plot_box")
                        )
                    )
            )
        )
    )
)


server <- function(input, output, session) {
    output$select_res_graph <- renderUI({list(selectizeInput(inputId = "select_result_graph",
                                                             label = "Choose Mechanism",
                                                             choices = colnames(results)[-c(1, 2, 3, 4, 5)]),
                                              selectizeInput(inputId = "select_var",
                                                             label = "Choose Variables",
                                                             choices = colnames(results)[1:4],
                                                             multiple = TRUE)
    )
    })

    output$plot_box <- renderUI({
        if (is.null(input$select_var))
            return(NULL)

        plot_output_list = lapply(1:length(input$select_var), function(i) {
            ggplot(results, aes(x = as.factor(get(input$select_result_graph)), 
                                y = get(input$select_var[i]), fill=factor(as.factor(input$select_result_graph)))) + 
                geom_boxplot() + theme(legend.position = "none")
           
        })

        for(i in 1:length(plot_output_list)){
            eval(parse(text  = sprintf("output$plot%i = renderPlot({plot_output_list[[%i]]})", i, i)))
        }
        
        eval(parse(text  = paste("tagList(", (paste("plotOutput('plot", 1:length(plot_output_list),"') ", sep = "", collapse = ",")), ")")))
    })
}

shinyApp(ui, server)

It seems the issue was that the tagList needed a plotOutput where each plot got a unique ID, but that didn't happen for some reason so the last plot was pasted in the n plots, as they did not have unique names.

I'm sure there are other ways to fix this, and I still don't fully understand how I got it working in the end, so please reply if you get additional insight !

Grtz

1 Like

Thanks! I just implemented the solution in my application and it works splendidly.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.