Can you visualize a plot in a tab by doing this in server.r?

Viewed 55

I am trying to save a plot to a list like here (where x is a counter):

pl_list[[x]] <- renderPlot({ggplot(dfg, aes(x="", y=mean_rel_abund, fill=taxon)) +
            geom_bar(stat="identity", width=1) +
            scale_fill_manual(values = v2, labels=paste(gsub('\\*', '', dfg$taxon), str_replace_all(paste(round(dfg$mean_rel_abund, 1),"%"), " ", "")))+
            # facet_grid(.~ data2()$disease_stat)+
            theme_classic() +
            theme(axis.line = element_blank(),
                  axis.text = element_blank(),
                  axis.ticks = element_blank())})

and then save the output of it like this:

output$pl_list[[x]] <- pl_list[[x]]

then visualize it in a tab by calling the plotOutput function:

appendTab(inputId = "tabs", tabPanel(title = input$caption, value = tid, 
                                         headerPanel('Microbiome'),
                                         mainPanel(
                                           plotOutput(pl_list[[tid]]),
                                           selectInput(inputId = shinyInput("case", rv$counter), label = strong("Case"),
                                                       choices = unique(data_list[[tid]]$disease_stat),
                                                       selected = "DiarrhealControl")
                                         ),
                                         
                                         actionButton(shinyInput("remove_btn", rv$counter), "Remove", icon = icon("minus-circle"))
                                         
    ))

But I'm getting an error where it says:

Warning: Error in $: Can't read output 'pl_list'

This is the whole code as someone requested:

library(shiny)
library(shinythemes)
library(tidyr)
library(tidyverse)
library(readxl)
library(ggtext)
library(RColorBrewer)
library(dplyr)
library(bslib)
library(shinydashboard)
library(tools)

tid <<- 0 
data_list <<- list()
pl_list <<- list()
ui <- fluidPage(
  textOutput("text"),
  tabsetPanel(id = "tabs",
              tabPanel(
                title = "Home",
                value = "home",
                sidebarLayout(
                  sidebarPanel(
                    h3("Generate plots"),
                    fileInput("probe1", "Metadata .XLSX File", accept = "xlsx", buttonLabel = "Browse"),
                    fileInput("probe2", "Otu_counts (subsample.shared) .TSV File", accept = "tsv", buttonLabel = "Browse"),
                    fileInput("probe3", "Taxonomy .TSV File", accept = "tsv", buttonLabel = "Browse"),
                    textInput("caption", "Name of the plot", "Example: plot1"),
                    verbatimTextOutput("value"),
                    actionButton("add", "Add", icon = icon("plus-circle"))
                  ),
                  mainPanel(
                    helpText("Description:"),
                    helpText("The required tables need to have information about:...")
                  )
                )
              ))
)

server <- function(input, output, session) {
  shinyInput <- function(name, id) paste(name, id, sep = "_")
  rv <- reactiveValues(counter = 0L)
  
  #go to the new created tab
  observeEvent(input$add, {
    rv$counter <- rv$counter + 1L
    updateTabsetPanel(session, "tabs", shinyInput("new_tab", rv$counter))
  }, ignoreInit = TRUE)
  
  #creating tab with plot after uploading the files
  observeEvent(input$add, {
    tid <<- tid + 1
    inputs <- reactiveValues(input1 = input$probe1, input2 = input$probe2, input3 = input$probe3)
    # print(inputs)
    # print(paste0("This is input1: ", inputs$input1))
    #data_list <<- append(data_list,
    
    #data processing
    metadata <- read_excel(inputs$input1$datapath, na="NA") %>%
      select(sample_id, disease_stat) %>%
      drop_na(disease_stat)
    
    otu_counts <- read_tsv(inputs$input2$datapath) %>%
      select(Group, starts_with("Otu")) %>%
      rename(sample_id = Group) %>%
      pivot_longer(-sample_id, names_to="otu", values_to = "count")
    
    taxonomy <- read_tsv(inputs$input3$datapath) %>%
      select("OTU", "Taxonomy") %>%
      rename_all(tolower) %>%
      mutate(taxonomy = str_replace_all(taxonomy, "\\(\\d+\\)", ""),
             taxonomy = str_replace(taxonomy, ";$", "")) %>%
      separate(taxonomy,
               into=c("kingdom", "phylum", "class", "order", "family", "genus"),
               sep=";")
    
    otu_rel_abund <- inner_join(metadata, otu_counts, by="sample_id") %>%
      inner_join(., taxonomy, by="otu") %>%
      group_by(sample_id) %>%
      mutate(rel_abund = count / sum(count)) %>%
      ungroup() %>%
      select(-count) %>%
      pivot_longer(c("kingdom", "phylum", "class", "order", "family", "genus", "otu"),
                   names_to="level",
                   values_to="taxon") %>%
      mutate(disease_stat = factor(disease_stat,
                                   levels=c("NonDiarrhealControl",
                                            "DiarrhealControl",
                                            "Case")))
    
    taxon_rel_abund <- otu_rel_abund %>%
      filter(level=="phylum") %>%
      group_by(disease_stat, sample_id, taxon) %>%
      summarize(rel_abund = sum(rel_abund), .groups="drop") %>%
      group_by(disease_stat, taxon) %>%
      summarize(mean_rel_abund = 100*mean(rel_abund), .groups="drop") %>%
      mutate(taxon = str_replace(taxon,
                                 "(.*)_unclassified", "Unclassified *\\1*"),
             taxon = str_replace(taxon,
                                 "^(\\S*)$", "*\\1*"))
    
    taxon_pool <- taxon_rel_abund %>%
      group_by(taxon) %>%
      summarize(pool = max(mean_rel_abund) < 3, 
                mean = mean(mean_rel_abund),
                .groups="drop")
    
    df <- inner_join(taxon_rel_abund, taxon_pool, by="taxon") %>%
      mutate(taxon = if_else(pool, "Other", taxon)) %>%
      group_by(disease_stat, taxon) %>%
      summarize(mean_rel_abund = sum(mean_rel_abund),
                mean = min(mean),
                .groups="drop") %>%
      mutate(taxon = factor(taxon),
             taxon = fct_reorder(taxon, mean, .desc=TRUE),
             taxon = fct_shift(taxon, n=1))
    #print(c(df))
    #print(df$taxon)
    dff <<- as.data.frame(df)
    data_list[[tid]] <<- dff
    
    #creating plot
    pl_list[[tid]] <- ggplot(data_list[[tid]], aes(x="", y=mean_rel_abund, fill=taxon)) +
      geom_bar(stat="identity", width=1) +
      # facet_grid(.~ data2()$disease_stat)+
      theme_classic() +
      theme(axis.line = element_blank(),
            axis.text = element_blank(),
            axis.ticks = element_blank())
    
    #print(paste("Before append:", data_list[[tid]]$disease_stat ))
    #output$plot <- render....
    
    #finally creating tab after data processing and plot creation
    appendTab(inputId = "tabs", tabPanel(title = input$caption, value = tid, 
                                         headerPanel('Microbiome'),
                                         mainPanel(
                                           plotOutput(pl_list[[tid]]),
                                           selectInput(inputId = shinyInput("case", rv$counter), label = strong("Case"),
                                                       choices = unique(data_list[[tid]]$disease_stat),
                                                       selected = "DiarrhealControl")
                                         ),
                                         
                                         actionButton(shinyInput("remove_btn", rv$counter), "Remove", icon = icon("minus-circle"))
                                         
    ))
    
    #print(pl_list[[tid]])
    #print(paste("After append", data_list[[tid]]$disease_stat))
    ##########################
    #print(inputs)
    
  })
  
  ## REACTIVITY TO ARRANGE TAB NAMES:
  current.tab <- eventReactive(input$tabs, {
    # don't accidentally remove main tab:
    if (!identical(input$tabs, "home")) {
      input$tabs
    } else {
      NULL
    }
  })
  
  
  #observe event for when a choice from a filter is selected
  observe({
    if (rv$counter > 0L) {
      lapply(seq(rv$counter), function(x) {
        observeEvent(input[[paste("case", x, sep = "_")]], {
          #filtering data based on the selected choice
          dfg <- filter(data_list[[tid]], disease_stat == input[[paste("case", x, sep = "_")]])
          #print(paste("this is dfg disease_stat:", dfg$disease_stat))
          v2 <- rainbow(length(dfg$taxon))
          names(v2) <- unique(dfg$taxon)
          #print(length(names(v2)))
          #print(paste(dfg$taxon, " ", round(dfg$mean_rel_abund, 1),"%"))
          if (length(names(v2)) == 1)
          {
            # v2["Other"] = "#FFFFFF"
          }
          else
          {
            v2["Other"] = "#808080"
            
          }
          #print(pl_list[[x]])
          #overwriting the first created plot on the tab with the newly created one based on the new data
          pl_list[[x]] <<- renderPlot({ggplot(dfg, aes(x="", y=mean_rel_abund, fill=taxon)) +
            geom_bar(stat="identity", width=1) +
            scale_fill_manual(values = v2, labels=paste(gsub('\\*', '', dfg$taxon), str_replace_all(paste(round(dfg$mean_rel_abund, 1),"%"), " ", "")))+
            # facet_grid(.~ data2()$disease_stat)+
            theme_classic() +
            theme(axis.line = element_blank(),
                  axis.text = element_blank(),
                  axis.ticks = element_blank())})
          #renderPlot(pl_list[[x]])
          #print(pl_list[[x]])
          output$pl_list[[x]] <- pl_list[[x]]
          
        })
      })
    }
  })
  
  #removing a tab
  observe({
    if (rv$counter > 0L) {
      lapply(seq(rv$counter), function(x) {
        observeEvent(input[[paste("remove_btn", x, sep = "_")]], {
          #print(paste0("This is x: ",x))
          removeTab(inputId = "tabs", target = current.tab())
          #print(paste0("Removing: ", input[[paste("remove_btn", x, sep = "_")]]))
        })
      })
    }
  })
  
  
  output$text <- renderText({paste0("You are viewing tab \"", input$tabs, "\"", " Rv$counter is: ", rv$counter)})
  
}

shinyApp(ui, server)

And link to the files you will need to upload in the shiny app:

https://drive.google.com/drive/folders/1bcGyE42aD5gicmdZseRGqvfT-Iu9FHLP

1 Answers

I fixed it by changing this line in the appendTab:

plotOutput(pl_list[[tid]])

to this:

plotOutput(paste("pl_list", tid, sep = "_"))

and this in the observe:

output$pl_list[[x]] <- pl_list[[x]]

to this:

output[[paste("pl_list", x, sep = "_")]] <- renderPlot({ pl_list[[x]] })
Related