有没有办法重置整个RShiny应用程序?

问题描述

我是RShiny的新手,一段时间以来我一直在尝试解决如何重置我的应用程序的问题,但是我还没有找到可行的解决方案。为了提出问题,我已经缩短了应用程序。共有三个标签:一个用于“数据上传”,一个用于“分析选项”,另一个用于显示生物标记的描述性统计信息。我希望我的整个应用在用户每次上传新数据集时都能恢复到原始状态。我试过使用Shinyjs的reset函数,但它只重置输入,因此当用户上载新数据集时,以前的输出仍显示在Descriptive Statistics选项卡中。每次用户上载新数据时,是否有可能有一个干净的状态,从而不会显示以前的输出?以下是我的应用的摘要:

ui.R

library(shinydashboard)
library(shinydashboardPlus)
library(dashboardthemes)
library(shiny)
library(openxlsx)
library(Cairo)
options(shiny.usecairo=T)
options(DT.TOJSON_ARGS = list(na = 'string'))

# Define UI ----
ui<-tagList(
  dashboardPage(
    dashboardHeader(title = shinyDashboardLogoDIY(boldText = "Stat",mainText = "App",textSize=30,badgeText = "v1",badgeTextColor = "white",badgeTextSize = 4,badgeBackColor = "rgb(44,62,80)",badgeBorderRadius = 3
    ),titleWidth = 275),dashboardSidebar(width = "275px",sidebarMenu(
                       menuItem("Data Upload",tabName = "upload",icon = icon("file-upload")),menuItem("Analysis",tabName = "opt",icon = icon("cogs")),menuItem("Descriptive Statistics",tabName = "st",icon=icon("calculator"))
                       
                     )
    ),dashboardBody(
      tags$head(tags$style(HTML('.info-box {min-height: 45px;} .info-box-icon {height: 63px; line-height: 60px; text-align: center; vertical-align: middle; } .info-box-content {padding-top: 0px; padding-bottom: 0px;}'))),tags$head(tags$style(HTML(".box {margin: 5px;}"))),waiter::waiter_show_on_load(html = tagList(waiter::spin_fading_circles(),"Loading ...")),tabItems(
        
        #Data Upload
        tabItem(tabName = "upload",fluidPage(
                  fluidRow(
                    box(status = "primary",width = 5,solidHeader=TRUE,title=strong("Please upload a .csv,.xls,or .xlsx file"),br(),fileInput("file1","Select File",accept = c(".csv",".xlsx",".xls")),conditionalPanel(condition="output.xlOut",uiOutput("xlOut")),selectizeInput("mname",label = helpText("Please select the marker name indicator:"),choices = NULL,options=list(maxOptions = 2000)),actionButton("goData","Submit")
                    ),fluidRow(
                      conditionalPanel(condition = "output.contents",box(status = "primary",width=12,DT::dataTableOutput("contents")))))
                )),#Analysis Options
        tabItem(tabName="opt",fluidRow(
                  column(12,offset=3,shinyjs::useShinyjs(),div(id = "anlysopt",box(status =  "primary",h2("Data Options"),box(title="Outcome Variable",status = "primary",solidHeader = TRUE,collapsible = TRUE,fluidRow(
                                column(5,selectizeInput("select.outcome",label = helpText("Please select the outcome variable:"),options=list(maxOptions = 2000)))),selectizeInput("select.case",label=helpText("Please select the cases:"),choices=NULL,options=list(maxOptions = 2000))),column(6,selectizeInput("select.ctrl",label=helpText("Please select the controls:"),options=list(maxOptions = 2000)))))
                      ))
                  )),shinyalert::useShinyalert(),# Set up shinyalert
                  waiter::use_waiter(),# Set up shinyalert
                  fluidRow(div(actionButton("goButton","Submit"),style="text-align: center;"))
                ),#Descriptive Statistics 
        tabItem(tabName = "st",fluidPage(
                  shinyjs::useShinyjs(),div(id = "stat",fluidRow(
                        valueBoxOutput("nsamp",width = 3),valueBoxOutput("ncase",valueBoxOutput("nctrl",valueBoxOutput("nbiom",width = 3)),fluidRow(box(width=12,status="primary",title="Descriptive Statistics",shinycssloaders::withSpinner(DT::dataTableOutput("desc"))))))
        )
      )
      
    )
    
  )
)

server.R

options(shiny.maxRequestSize=30*1024^2)
server <- function(input,output,session) {
  waiter::waiter_hide() # will hide *on_load waiter
  
  #User upload
  d0<-reactive({
    
    inFile <- input$file1
    
    if (is.null(inFile))
      return(NULL)
    
    getExtension <- function(file){
      ex <- strsplit(basename(file),split="\\.")[[1]]
      return(ex[-1])
    }
    
    p.ext=getExtension(inFile$datapath)
    
    return(list(inFile=inFile,p.ext=p.ext))
  })
  
  #If user uploads excel file,they chose an excel sheet to analyze 
  output$xlOut<-renderUI({
    req(input$file1)
    if(d0()$p.ext=="xlsx"|d0()$p.ext=="xls"){
      ch=readxl::excel_sheets(input$file1$datapath)
      selectizeInput("selectxl",label = "Choose an excel sheet:",choices = ch)
      
    }
  })
  outputOptions(output,'xlOut',suspendWhenHidden=FALSE)
  
  
  #Read data set
  Data0<-reactive({
    
    req(input$file1,d0()$p.ext)
    if(d0()$p.ext=="csv"){
      newdat<-read.csv(input$file1$datapath,header=F,stringsAsFactors = F)
      newdat.df<-as.data.frame(newdat)
      
      w1=as.numeric(length(which(newdat.df[,1]==""))+1) #row
      w2=as.numeric(length(which(newdat.df[1,]==""))+1) #col
      
    }else if(d0()$p.ext=="xlsx"|d0()$p.ext=="xls"){
      req(input$selectxl)
      sh=paste0(input$selectxl,sep="")
      
      newdat<-readxl::read_excel(input$file1$datapath,sheet=sh,col_names =F)
      newdat.df<-as.data.frame(newdat)
      
      w1=as.numeric(which(duplicated(cumsum(is.na(newdat.df[,1])))==TRUE)[1]) #row
      w2=as.numeric(which(duplicated(cumsum(is.na(newdat.df[1,])))==TRUE)[1]) #col
    }
    
    return(list(ns=newdat.df,row=w1,col=w2))
  })
  
  #User chooses name of markers 
  observe({

    req(input$file1,Data0()$ns)
    mname.ch=Data0()$ns[c(1:(Data0()$row-1)),Data0()$col]

    updateSelectizeInput(session,"mname",label = "Please select the marker name indicator:",choices = mname.ch)
  })
  
  
  #Finalized data based on user marker selection 
  Data<-reactive({
    
    req(input$mname)
    w4=which(Data0()$ns[,Data0()$col]==input$mname)
    
    #New data
    dataf2=Data0()$ns[-c(1:Data0()$row),]
    colnames(dataf2)[1:Data0()$col]=Data0()$ns[Data0()$row,1:Data0()$col]
    colnames(dataf2)[(Data0()$col+1):ncol(dataf2)]=Data0()$ns[w4,(Data0()$col+1):ncol(dataf2)]
    
    return(list(wide=dataf2))
  })
  
  
  #Only display data after file is uploaded (no prior error)
  dis <- eventReactive(input$goData,{
    input$contents
  })
  
  #Display data (wide format)
  output$contents <- DT::renderDataTable(rownames=FALSE,options = list(pageLength=25,scrollX = TRUE),{
    
    dis()
    isolate(Data()$wide)
  })
  outputOptions(output,'contents',suspendWhenHidden=FALSE)
  
  
  #Auto-fill drop-down list to select outcome
  observeEvent(input$mname,{

    req(Data()$wide)
    col.w1 <- colnames(Data()$wide)

    # Can use character(0) to remove all choices
    if (is.null(col.w1))
      col.w1 <- character(0)

    # Can also set the label and select items
    updateSelectizeInput(session,"select.outcome",label = "Please select the outcome variable:",choices = col.w1)

  })


  #Auto-fill drop-down list to select cases/ctrls
  observeEvent(input$select.outcome,{

    req(Data()$wide)
    outc=Data()$wide[,which(colnames(Data()$wide)==input$select.outcome)]

    # Can also set the label and select items
    updateSelectizeInput(session,"select.case",label = "Please select the cases:",choices = outc)

    updateSelectizeInput(session,"select.ctrl",label = "Please select the controls:",choices = outc)

  })
  
  
  
  #Data Step: Determine Outcome & markers depending on user input
  Data_outlong<-reactive({
    
    data=Data()$wide
    col=Data0()$col
    
    #Outcome and Z
    y=sapply(data[,which(colnames(data)==input$select.outcome)],as.numeric)
    z=sapply(data.frame(data[,c((col+1):ncol(data))]),as.numeric)
    colnames(z)=colnames(data)[c((col+1):ncol(data))]
    
    return(list(y=y,z=z))
  })
  
  #Give error if n1<1 or n0<1
  observeEvent(input$goButton,{
    y=Data_outlong()$y
    len=length(unique(y))
    
    x=tryCatch(len,warning=function(w){ w })
    
    if(x<2){
      shinyalert::shinyalert("Error","Outcome variable must have more than one level",type="error",immediate = T)
    }else if (x>=2){
      
      
      #Display results of "Descriptive Statistics" tab only after click submit
      react <- eventReactive(input$goButton,{
        
        input$stats
        input$desc
        
      })
      
      #Waiter and Shiny Alert after "Analysis Options"
      observeEvent(input$goButton,once = T,{
        
        waiter::waiter_show(html = waiter::spin_fading_circles())
        waiter::waiter_hide()
        shinyalert::shinyalert("Analysis Complete",type = "success",immediate = T)
        
      })
      
      
      #Descriptive Stat calc
      stats<-reactive({
        
        req(input$goButton,Data_outlong(),input$select.case,input$select.ctrl)

        #Outcome and z
        y=Data_outlong()$y
        z=Data_outlong()$z
        
        if(is.character(y)){ #if y is character: "case","control",etc.....
          ca=input$select.case
          ctr=input$select.ctrl
        }else if(is.numeric(y)){ #if y is numeric: 0,1,etc.....
          ca=as.numeric(input$select.case)
          ctr=as.numeric(input$select.ctrl)
        }
        
        #Descriptive
        n.samp=nrow(z)
        cas=which(y==ca)
        cont=which(y==ctr)
        n.case=length(cas)
        n.ctrl=length(cont)
        n.bio=ncol(z)
        
        stat.df=data.frame(SAMP=n.samp,CASE=n.case,CTRL=n.ctrl,BIO=n.bio)
        
        case=data.frame(z[cas,])
        colnames(case)=colnames(z)
        ctrl=data.frame(z[cont,])
        colnames(ctrl)=colnames(z)
        
        desc.over=t(round(apply(z,2,function(x) { c(mn = mean(x),std = sd(x),med=median(x),q1=quantile(x)[[2]],q3=quantile(x)[[4]])}),2))
        desc.over=data.frame("All Samples",desc.over)
        desc.over <- cbind(rownames(desc.over),data.frame(desc.over,row.names=NULL))
        colnames(desc.over)[1:2]=c("Markers","Category")
        
        
        desc.case=t(round(apply(case,2))
        desc.case=data.frame("Cases",desc.case)
        desc.case <- cbind(rownames(desc.case),data.frame(desc.case,row.names=NULL))
        colnames(desc.case)[1:2]=c("Markers","Category")
        
        desc.ctrl=t(round(apply(ctrl,2))
        desc.ctrl=data.frame("Controls",desc.ctrl)
        desc.ctrl <- cbind(rownames(desc.ctrl),data.frame(desc.ctrl,row.names=NULL))
        colnames(desc.ctrl)[1:2]=c("Markers","Category")
        
        desc.df=rbind(desc.over,desc.case,desc.ctrl)
        colnames(desc.df)[3:7]<-c("Mean","Standard Deviation","Median","Q1","Q3")
        desc.df=desc.df[order(desc.df$Markers),]
        
        return(list(stat=stat.df,desc=desc.df,CAS=cas,CONT=cont))
        
      })
      
      
      #ValueBox- No of samples
      output$nsamp <- renderValueBox({
        react()
        valueBox(
          paste0(stats()$stat$SAMP),"Number of Samples",icon = icon("vials"),color="aqua"
        )
      })
      
      #ValueBox- No of Cases
      output$ncase <- renderValueBox({
        react()
        valueBox(
          paste0(stats()$stat$CASE),"Number of Cases",icon = icon("briefcase-medical"),color="aqua"
        )
      })
      
      #ValueBox- No of Controls
      output$nctrl <- renderValueBox({
        react()
        valueBox(
          paste0(stats()$stat$CTRL),"Number of Controls",icon = icon("briefcase"),color="aqua"
        )
      })
      
      #ValueBox- No of Biomarkers
      output$nbiom <- renderValueBox({
        react()
        valueBox(
          paste0(stats()$stat$BIO),"Number of Biomarkers",icon = icon("microscope"),color="aqua"
        )
      })
      
      #Descriptive Statistics Table pt 2
      output$desc <- DT::renderDataTable(rownames=FALSE,extensions = c('Buttons','RowGroup'),scrollX = TRUE,rowGroup = list(dataSrc=c(0))),{
                                                          
                                                          react()
                                                          isolate(stats()$desc)
    })
      
    }
  })
  
  #Reset Inputs
  observeEvent(input$file1,{
    shinyjs::reset("anlysopt")
    shinyjs::reset("stat")

  })
  
}

以下是使用我随附的特定测试数据集时在应用程序中进行的选择:

  • 请选择标记物名称指示器:蛋白质
  • 请选择结果变量: CaCo
  • 请选择案例: 1
  • 请选择控件: 0

链接到数据集:https://www.dropbox.com/s/sv3c0qodf70mk8t/Sample%20Data.csv?dl=0

任何帮助将不胜感激!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)