Problem with shiny app creation and output in R

I'm very new in creating a shiny app. Need some help in resolving the errors. So, I have some data like below in file final.csv:

structure(list(Samples = structure(c(1L, 12L, 23L, 34L, 45L, 
46L, 47L, 48L, 49L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 24L, 25L, 26L, 
27L, 28L, 29L, 30L, 31L, 32L, 33L, 35L, 36L, 37L, 38L, 39L, 40L, 
41L, 42L, 43L, 44L), .Label = c("Sample1", "Sample10", "Sample11", 
"Sample12", "Sample13", "Sample14", "Sample15", "Sample16", "Sample17", 
"Sample18", "Sample19", "Sample2", "Sample20", "Sample21", "Sample22", 
"Sample23", "Sample24", "Sample25", "Sample26", "Sample27", "Sample28", 
"Sample29", "Sample3", "Sample30", "Sample31", "Sample32", "Sample33", 
"Sample34", "Sample35", "Sample36", "Sample37", "Sample38", "Sample39", 
"Sample4", "Sample40", "Sample41", "Sample42", "Sample43", "Sample44", 
"Sample45", "Sample46", "Sample47", "Sample48", "Sample49", "Sample5", 
"Sample6", "Sample7", "Sample8", "Sample9"), class = "factor"), 
    years = c(1.301369863, 0.4, 1.054794521, 0.134246575, 0.794520548, 
    3.287671233, 3.646575342, 3.887671233, 3.646575342, 3.619178082, 
    3.575342466, 2.02739726, 3.523287671, 3.742465753, 2.926027397, 
    3.8, 1.161643836, 1.380821918, 3.087671233, 3.104109589, 
    3.084931507, 2.887671233, 2.778082192, 2.728767123, 3.043835616, 
    1.210958904, 2.704109589, 2.742465753, 2.635616438, 2.536986301, 
    2.432876712, 2.794520548, 1.967123288, 1.84109589, 1.838356164, 
    2.726027397, 2.430136986, 2.257534247, 1.876712329, 2.010958904, 
    0.698630137, 2.090410959, 2.098630137, 2.01369863, 1.717808219, 
    1.81369863, 2.057534247, 2.032876712, 1.989041096), patient.vital_status = c(0L, 
    0L, 0L, 1L, 1L, 0L, 1L, 0L, 0L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 
    1L, 1L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L), A1BG = structure(c(1L, 1L, 2L, 2L, 1L, 2L, 2L, 
    1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 
    2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 
    1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L), .Label = c("high", 
    "low"), class = "factor"), A1CF = structure(c(1L, 1L, 1L, 
    1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 
    2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    2L), .Label = c("high", "low"), class = "factor")), class = "data.frame", row.names = c(NA, 
-49L))

Using the above information I'm trying to create an app, but having some trouble to make it correct. Below is the code I used:

library(shiny)
library(shinyjs)
library(tidyverse)
library(survminer)

ui <- fluidPage(
  titlePanel("survival"),
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "thegene", label = "Gene", choices = c("A1BG", "A1CF"), selected = "A1CF"),
      radioButtons(inputId = "FileType", label = "Select the file type", choices = list("png", "pdf"), selected = "pdf"),
      width = 3
    ),
    mainPanel(
      plotOutput("plot"),
      downloadButton(outputId = "downloadPlot", label = "Download the plot"),
      width = 9
    )
  )
)

server <- function(input, output, session) {
  final <- read.csv("final.csv")
  genes <- as.factor(names(final[c(4:5)]))
  
  vals <- reactiveValues()
  
  alldat <- reactive({
    choices <- genes
    selected <- isolate(input$thegene)
    if (!selected %in% choices) selected <- choices[1]
    updateSelectInput(session, "thegene", choices = choices, selected = selected)
    final
  })
  
  dat <- reactive({
    x <- alldat()
    x[ x$variable == input$thegene,,drop=FALSE]
  })
  
  output$plot <- renderPlot({
      fit <- survfit(as.formula(paste0("Surv(years, patient.vital_status) ~", names(final[c(4:5)]))),
                     data = final)
      gg <-ggsurvplot(fit,
                 pval = TRUE, conf.int = FALSE,
                 risk.table = TRUE, # Add risk table
                 risk.table.col = "strata", # Change risk table color by groups
                 linetype = "strata", # Change line type by groups
                 surv.median.line = "hv", # Specify median survival
                 ggtheme = theme_bw(), # Change ggplot2 theme
                 palette = c("#FF0027", "#060606"),
                 xlim = c(0,10),
                 break.x.by = 3,
                 xlab="Time in years",
                 risk.table.y.text.col = T, # colour risk table text annotations.
                 risk.table.y.text = FALSE)
    vals$gg <- gg
    print(gg)
  })
  
  output$downloadPlot <- downloadHandler(
    filename =  function() {
      paste(input$thegene, input$FileType,sep=".")
    },
    # content is a function with argument file. content writes the plot to the device
    content = function(file){
      if(input$FileType=="png")
        png(file, units="in", width=5, height=5, res=300)
      else
        pdf(file, width = 5, height = 5, onefile = FALSE)
      print(vals$gg)
      dev.off()
    } 
  )
}

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

With the above code when I run the app, I have an error.

Error: object 'final' not found

As I see the above ERROR, so before running the app I loaded the final.csv and also assigned the column names of 4th and 5th column to genes myself. And then when I run the app looks like it worked but, I could see only A1BG gene output. When I selected A1CF gene in the interface, I don't see that output instead I see again A1BG output.

Debugging shiny is tricky. I usually pepper my code with cat() and print() statements to keep track of which bits are being run and what values are being passed between reactive elements.

I tried to run your app.

Warning: Error in survfit: could not find function "survfit"

This bit looks strange. There is nothing reactive inside it so it will only run once. You might need to consider the environments. And assuming this reactive context has access to genes and final, it will always return a value of final. So the dat <- reactive will only trigger if input$thegene changes. Might be worth reading up on reactivity.

alldat <- reactive({
    choices <- genes
    selected <- isolate(input$thegene)
    if (!selected %in% choices) selected <- choices[1]
    updateSelectInput(session, "thegene", choices = choices, selected = selected)
    final
  })

I think this is missing some brackets:

if (!(selected %in% choices)){ selected <- choices[1] }

Warning: Error in survfit: could not find function "survfit" for this you have to load package survival

I added library(survival) and the app runs without errors. Just the non-reactive problems I mentioned above.

When you run the app, it runs in its own environment, no packages or data you have loaded in the global environment will be available.

I think you can simplify this quite a bit. I usually use observeEvent as it's easier to control. Change alldat <- reactive to observeEvent to update thegene, and then I think you can do most of what you want inside of output$plot <- renderPlot({ ... })

could you please post the whole code once which you used and didn't get any errors. thanq

Same as your code above plus I added library(survival)

But with the above code of mine I'm having error which I mentioned above and if I load that csv file myself and then run the app, I could get the plot of only A1BG and I don't see A1CF plot.

I created the final.csv file from your structure and put it in the project directory. I created an R script using your code and added library(survival). Then I clicked Run App and it ran without errors.

Yes you need to fix your reactivity, you can't change the plot.

If I dont load the file myself, I'm still getting the same error.

Warning: Error in eval: object 'final' not found

What does the console log say?

Warning: Error in eval: object 'final' not found
173: eval
172: eval
171: .get_data
170:
168: ggsurvplot
167: renderPlot [/Users/Documents/Softwares/MyShiny/jki/app.R#112]
165: func

I mean the whole console log from when you start the app.

sorry not aware about. could you please tell me how do I get that.

Hi @beginner2. The survfit function seems work in it own environment. So, it seem cannot pass anything into it to construct the formula. You can try the following code. I construct the whole script and eval it at once. It work. Hope it can help.

library(shiny)
library(shinyjs)
library(tidyverse)
library(survminer)
library(survival)



ui <- fluidPage(
  titlePanel("survival"),
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "thegene", label = "Gene", choices = c("A1BG", "A1CF"), selected = "A1CF"),
      radioButtons(inputId = "FileType", label = "Select the file type", choices = list("png", "pdf"), selected = "pdf"),
      width = 3
    ),
    mainPanel(
      plotOutput("plot"),
      downloadButton(outputId = "downloadPlot", label = "Download the plot"),
      width = 9
    )
  )
)

server <- function(input, output, session) {
  final <- read.csv("final.csv")
  genes <- as.factor(names(final[c(4:5)]))
  
  vals <- reactiveValues()
  
  alldat <- reactive({
    choices <- genes
    selected <- isolate(input$thegene)
    if (!selected %in% choices) selected <- choices[1]
    updateSelectInput(session, "thegene", choices = choices, selected = selected)
    final
  })
  
  dat <- reactive({
    x <- alldat()
    x[ x$variable == input$thegene,,drop=FALSE]
  })
  
  output$plot <- renderPlot({
    fit <- eval(parse(text = paste0("survfit(Surv(years, patient.vital_status) ~ ", input$thegene, ", data = final)")))
    gg <-ggsurvplot(fit,
                    pval = TRUE, conf.int = FALSE,
                    risk.table = TRUE, # Add risk table
                    risk.table.col = "strata", # Change risk table color by groups
                    linetype = "strata", # Change line type by groups
                    surv.median.line = "hv", # Specify median survival
                    ggtheme = theme_bw(), # Change ggplot2 theme
                    palette = c("#FF0027", "#060606"),
                    xlim = c(0,10),
                    break.x.by = 3,
                    xlab="Time in years",
                    risk.table.y.text.col = T, # colour risk table text annotations.
                    risk.table.y.text = FALSE)
    vals$gg <- gg
    print(gg)
  })
  
  output$downloadPlot <- downloadHandler(
    filename =  function() {
      paste(input$thegene, input$FileType,sep=".")
    },
    # content is a function with argument file. content writes the plot to the device
    content = function(file){
      if(input$FileType=="png")
        png(file, units="in", width=5, height=5, res=300)
      else
        pdf(file, width = 5, height = 5, onefile = FALSE)
      print(vals$gg)
      dev.off()
    } 
  )
}

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

When you click "Run App" in RStudio there is a log in the Console Pane. On my setup it is at the bottom of the screen. When I run your app it shows:

> runApp('shiny_final.R')

Listening on http://127.0.0.1:5727

This is what I see in console.

Listening on http://127.0.0.1:4727
Warning: Error in eval: object 'final' not found
173: eval
172: eval
171: .get_data
170:
168: ggsurvplot
167: renderPlot [/Users/Documents/Softwares/MyShiny/jki/app.R#112]
165: func

This is what I see in console.

Listening on http://127.0.0.1:4727
Warning: Error in eval: object 'final' not found
  173: eval
  172: eval
  171: .get_data
  170: <Anonymous>
  168: ggsurvplot
  167: renderPlot [/Users/Documents/Softwares/MyShiny/jki/app.R#112]
  165: func
  125: drawPlot
  111: <reactive:plotObj>
   95: drawReactive
   82: origRenderFunc
   81: output$plot
    1: runApp

Hi, @raytong thanks a lot for the reply. Actually, if I load the final.csv file myself and then run the app everything works fine. But without loading the csv file, if I run the app, I still see the same error. Please bear with me.

Warning: Error in eval: object 'final' not found

  • make a note of the current working directory getwd()
  • check if the csv file is stored on the same path as the working directory
  • if not, either save the file to the current working directory path or provide the absolute path (exact address of the file starting from root directory) in read.csv(file = 'C:/path_to_file/final.csv')

My working directory is /Users/Documents/Softwares/test

Inside the directory test I have the final.csv file. Also app.R.

Inside app.R I gave the setwd("/Users/Documents/Softwares/test") first and then the whole code. For the csv file also I gave the path.

And still, if I don't load the file myself I get the same error.

Warning: Error in eval: object 'final' not found