Problem with shiny app creation and output in R

@beginner2. I also get this error when run your code. And the error was come from the evaluation of the following code.

fit <- survfit(as.formula(paste0("Surv(years, patient.vital_status) ~", names(final[c(4:5)]))),
                     data = final)

The final[c4:5] raise error in evaluation that object not found. The reason may due to the evaluation environment problem. This kind of problem sometimes happen. The most easy way to fix this is to construct the code in string and evaluation it at once.

fit <- eval(parse(text = paste0("survfit(Surv(years, patient.vital_status) ~ ", input$thegene, ", data = final)")))

Moreover, your code have one more problem is the formula as.formula(paste0("Surv(years, patient.vital_status) ~", names(final[c(4:5)]))). Even your code work, it only calculate the gene A1BG only, because it use the first element in the names vector. So, I directly construct the formula using the input$thegene to update the survival plot.

@raytong Yes I understand that. But even with eval I'm having the error. And I'm not sure why I have to load the final.csv file myself. If I dont load the file myself Warning: Error in eval: object 'final' not found

Both app.R and final.csv were kept in /Users/Documents/Softwares/test

This is the code inside app.R

setwd("/Users/Documents/Softwares/test")
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(file = "/Users/Documents/Softwares/test/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)

And if I load the file myself and run the app evrything works without any error.

@beginner2. The problem was interesting and strange. First, the resulting object of survfit is a collection of informations for lazy evaluation. So, if you run it with a formula that evaluation needed like yours, it will save the expression only and evaluate later will raise error that object not found.

Second, the ggsurvplot also cannot get final from environment but it can get it from .GlobalEnv. So, if you load it to .GlobalEnv will work but load it in evaluation environment not work. You can pass final into ggsurvplot environment by argument data will solve it. Hope I make myself clear. And this was an interesting question.:grin:

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)]))
  env <- parent.frame()
  
  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,
                    data = final,
                    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

Excellent @raytong yes got the point now. thanq very much for the help. This works now without any error.

@raytong One small question. I have two different datasets. With one dataset I made a histogram plot and with other dataset a scatter plot and want to show this two plots in a single shiny app with different windows. Is it possible to do that in shiny? If so, could you please share some links or examples. thanq

@beginner2. Of course can plot a number of plots. Just layout different plotOutput in ui and code to plot graph in corresponding renderPlot in server. You can get many examples at Shiny-Gallery.

1 Like

Sure will have a look at it. thanks a lot.

The problem is you set the working directory using setwd. Don't do this in shiny. The app runs in a temporary directory so it won't find your file. Actually don't do this ever.

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