0

I'm pretty new to shiny (being playing around for about a week). And I'm trying to create an app that takes and input tab-separated text file and perform several exploratory functions. In this case I'm presenting a very simplified version of that app just to highlight what I want to do in a specific case:

Problem:

If you try the app with the sample data (or any data in the same format) you can notice that the app effectively performs the default summary table (if selectInput="summarize", then output$sumfile), but when you try to select "explore", the previous table gets removed from the mainPanel, and outputs the full file (selectInput="explore",then output$gridfile) in the place where it would be as if selectInput="summarize" was still selected.

If you re-select "summarize", excelOutput("sumfile") gets duplicated on the mainPanel.

My goal is simple:

excelOutput("sumfile") when selectInput="summarize" ONLY and

excelOutput("gridfile") when selectInput="explore" ONLY

without placement issues or duplications on the mainPanel

So far I've tried:

inFile=input$df

if(is.null(inFile))
  return(NULL)

if(input$show=="summarize") 
  return(NULL)

or

inFile=input$df

if(is.null(inFile))
  return(NULL)

if(input$show=="explore") 
     return(NULL)

To control what shows up on the mainPanel, but with placement and duplication issues.

sample data:

#Build test data
testdat<-data.frame(W=c(rep("A",3),
                        rep("B",3),
                        rep("C",3)),
                    X=c(letters[1:9]),
                    Y=c(11:19),
                    Z=c(letters[1:7],"",NA),
                    stringsAsFactors = FALSE)
#Export test data
write.table(testdat,
            "your/path/file.txt",
            row.names = FALSE,
            sep = "\t",
            quote = FALSE,
            na="")

shiny app (app.R):

library(shiny)
library(excelR)

#function to summarize tables
Pivot<-function(df){
  cclass<-as.character(sapply(df,
                              class))
  df.1<-apply(df,
              2,
              function(x) unlist(list(nrows = as.numeric(NROW(x)),
                                      nrows.unique = length(unique(x))-(sum(is.na(x))+length(which(x==""))),
                                      nrows.empty = (sum(is.na(x))+length(which(x==""))))))

  df.2<-data.frame(df.1,
                   stringsAsFactors = FALSE)
  df.3<-data.frame(t(df.2),
                   stringsAsFactors = FALSE)
  df.3$col.class<-cclass
  df.3$col.name<-row.names(df.3)
  row.names(df.3)<-NULL
  df.3<-df.3[c(5,4,1,2,3)]
  return(df.3)
}

ui <- fluidPage(
  ui <- fluidPage(titlePanel(title=h1("Summary generator",
                                      align="center")),
                  sidebarLayout(
                    sidebarPanel(
                      h3("Loading panel",
                         align="center"),
                      fileInput("df", 
                                "Choose file (format: file.txt)",
                                accept = c("plain/text",
                                           ".txt")),
                      selectInput("show",
                                  "Choose what to do with file",
                                  choices=c("summarize","explore")),
                      p("**'summarize' will output a summary of the selected table"),
                      p("**'explore' will output the full selected editable table"),

                      tags$hr()

                    ),
                    mainPanel(
                      excelOutput("gridfile"),
                      excelOutput("sumfile")
                    ))))


server <- function(input, output) {
  dat<-reactive({
    fp<-input$df$datapath
    read.delim(fp, 
               quote="", 
               na.strings="\"\"", 
               stringsAsFactors=FALSE)
  })
  #get summary
  output$sumfile<-renderExcel({
    inFile=input$df

    if(is.null(inFile)) #if fileInput is empty return nothing
      return(NULL)

    if(input$show=="explore") #if selectInput = "explore" return nothing
      return(NULL)

    dat.1<-data.frame(dat())
    dat.2<-Pivot(dat.1)
    excelTable(dat.2,
               defaultColWidth = 100,
               search = TRUE)

  })
  #get full file
  output$gridfile<-renderExcel({
    inFile=input$df

    if(is.null(inFile)) #if fileInput is empty return nothing
      return(NULL)

    if(input$show=="summarize") #if selectInput = "summarize" return nothing
      return(NULL)
    dat.1<-data.frame(dat())
    excelTable(dat.1,
               defaultColWidth = 100,
               search = TRUE)

  })
}

shinyApp(ui = ui, server = server)


marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • The previous table gets removed because you are returning null when the other option is selected. Instead of that you should check if the rendered table is null. – SBista Aug 21 '19 at 03:53

1 Answers1

0

One way to do what you want is to use observeEvent for your inputs input$show and input$df and renderExcel based on your selection of `input$show. Here is an updated version for your code:

library(shiny)
library(excelR)

#function to summarize tables
Pivot<-function(df){
  cclass<-as.character(sapply(df,
                              class))
  df.1<-apply(df,
              2,
              function(x) unlist(list(nrows = as.numeric(NROW(x)),
                                      nrows.unique = length(unique(x))-(sum(is.na(x))+length(which(x==""))),
                                      nrows.empty = (sum(is.na(x))+length(which(x==""))))))

  df.2<-data.frame(df.1,
                   stringsAsFactors = FALSE)
  df.3<-data.frame(t(df.2),
                   stringsAsFactors = FALSE)
  df.3$col.class<-cclass
  df.3$col.name<-row.names(df.3)
  row.names(df.3)<-NULL
  df.3<-df.3[c(5,4,1,2,3)]
  return(df.3)
}

ui <- fluidPage(
  ui <- fluidPage(titlePanel(title=h1("Summary generator",
                                      align="center")),
                  sidebarLayout(
                    sidebarPanel(
                      h3("Loading panel",
                         align="center"),
                      fileInput("df",
                                "Choose file (format: file.txt)",
                                accept = c("plain/text",
                                           ".txt")),
                      selectInput("show",
                                  "Choose what to do with file",
                                  choices=c("summarize","explore")),
                      p("**'summarize' will output a summary of the selected table"),
                      p("**'explore' will output the full selected editable table"),

                      tags$hr()

                    ),
                    mainPanel(
                      excelOutput("gridfile"),
                      excelOutput("sumfile")
                    ))))


server <- function(input, output) {
  dat<-reactive({
    fp<-input$df$datapath
    read.delim(fp,
               quote="",
               na.strings="\"\"",
               stringsAsFactors=FALSE)
  })

  observeEvent({
    input$show
    input$df
    }, {
    inFile=input$df
    if(is.null(inFile)) #if fileInput is empty return nothing
      return(NULL)

    if(input$show=="explore") {
      output$gridfile<-renderExcel({

        dat.1<-data.frame(dat())
        excelTable(dat.1,
                   defaultColWidth = 100,
                   search = TRUE)

      })
    }

    if(input$show=="summarize") {
      output$sumfile<-renderExcel({

        dat.1<-data.frame(dat())
        dat.2<-Pivot(dat.1)
        excelTable(dat.2,
                   defaultColWidth = 100,
                   search = TRUE)

      })
    }
  })

}

shinyApp(ui = ui, server = server)

Hope it helps!

SBista
  • 7,479
  • 1
  • 27
  • 58