0
votes

Building on code examples found on Stack Overflow, I have built my first shiny app that behaves as expected. I can load a datafile and perform various statistical tasks on variables in the dataframe.

My ui.r and server.r scripts are below.

I would like to modify the code so that the main panel has only a single output window; currently it has one window for each possible action button. The current example has only three tasks: str(), cor(), and lm().

What I am trying to accomplish is that the result of any tasks would appear in the single window. If the user chooses a different action, the window would update with the new result.

Can anyone point to a worked example that does this I can study or suggest a way to modify my code accordingly?

ui.r

library(shiny)
shinyUI(fluidPage(
titlePanel("Multiple Linear Regression"),
sidebarLayout(
sidebarPanel(
  fileInput('file1', 'Choose File',
            accept=c('text/csv', 
                     'text/comma-separated-values,text/plain', 
                     '.csv')),

  tags$hr(),
  checkboxInput('header', 'Header', TRUE),

  radioButtons('sep', 'Separator',
    c(Comma=',',
    Semicolon=';',
    Tab='\t'),
    'Comma'),

  radioButtons('quote', 'Quote',
    c(None='',
    'Double Quote'='"',
    'Single Quote'="'"),
    'Double Quote'),

  actionButton("structure", "View data structure"),

  uiOutput("dependent"),
  uiOutput("independents"),
  tags$hr(),
  actionButton("regression", "Linear regression"),
  actionButton("correlation", "Correlation")

),
mainPanel(
  verbatimTextOutput('structure'),
  verbatimTextOutput('regression'),
  verbatimTextOutput('correlation')
)
)
))

server.r

library(shiny)
shinyServer(function(input, output) {

filedata <- reactive({
infile <- input$file1
if (is.null(infile)){
  return(NULL)      
}

read.csv(infile$datapath, sep=input$sep, quote=input$quote)

})

output$dependent <- renderUI({
df <- filedata()
if (is.null(df)) return(NULL)
items=names(df)
names(items)=items
selectInput("dependent","Select dependent variable from:",items)
})


output$independents <- renderUI({
df <- filedata()
if (is.null(df)) return(NULL)
items=names(df)
names(items)=items
selectInput("independents","Select variable(s) from:",items,multiple=TRUE)
})

output$structure <- renderPrint({
input$structure
isolate({   
  df <- filedata()
  str(df)
})   
})

output$regression <- renderPrint({
input$regression
isolate({   
  df <- filedata()
  if (is.null(df)) return(NULL)
  fmla <- as.formula(paste(input$dependent," ~  ",paste(input$independents,collapse="+")))
  summary(lm(fmla,data=df))
})   
})

output$correlation <- renderPrint({
input$correlation
isolate({   
  df <- filedata()
  if (is.null(df)) return(NULL)
  vars <- c(input$dependent, input$independents)
  cor(df[,vars])
})   
})

}) 
1

1 Answers

0
votes

Harold,

There are a couple of ways to accomplish this. If you want to keep your action buttons, I would introduce a reactive variable to decide what task to perform. Here's the modified code:

ui.r

library(shiny)
shinyUI(fluidPage(
  titlePanel("Multiple Linear Regression"),
  sidebarLayout(
    sidebarPanel(
      fileInput('file1', 'Choose File',
                accept=c('text/csv',
                         'text/comma-separated-values,text/plain',
                         '.csv')),

      tags$hr(),
      checkboxInput('header', 'Header', TRUE),

      radioButtons('sep', 'Separator',
                   c(Comma=',',
                     Semicolon=';',
                     Tab='\t'),
                   'Comma'),

      radioButtons('quote', 'Quote',
                   c(None='',
                     'Double Quote'='"',
                     'Single Quote'="'"),
                   'Double Quote'),

      actionButton("structure", "View data structure"),

      uiOutput("dependent"),
      uiOutput("independents"),
      tags$hr(),
      actionButton("regression", "Linear regression"),
      actionButton("correlation", "Correlation")

    ),
    mainPanel(
      verbatimTextOutput('alloutput')
    )
  )
))

server.r

library(shiny)
shinyServer(function(input, output) {

  filedata <- reactive({
    infile <- input$file1
    if (is.null(infile)){
      return(NULL)
    }

    read.csv(infile$datapath, sep=input$sep, quote=input$quote)

  })

  output$dependent <- renderUI({
    df <- filedata()
    if (is.null(df)) return(NULL)
    items=names(df)
    names(items)=items
    selectInput("dependent","Select dependent variable from:",items)
  })


  output$independents <- renderUI({
    df <- filedata()
    if (is.null(df)) return(NULL)
    items=names(df)
    names(items)=items
    selectInput("independents","Select variable(s) from:",items,multiple=TRUE)
  })

  viewStructure <- function(){
    df <- filedata()
    str(df)
  }

  doRegression <- function(){
    df <- filedata()
    if (is.null(df)) return(NULL)
    fmla <- as.formula(paste(input$dependent," ~  ",paste(input$independents,collapse="+")))
    summary(lm(fmla,data=df))
  }

  doCorrelation <- function(){
    df <- filedata()
    if (is.null(df)) return(NULL)
    vars <- c(input$dependent, input$independents)
    cor(df[,vars])
  }

  task <- reactiveValues(name="")
  observeEvent(input$structure, task$name <- 'structure')
  observeEvent(input$regression, task$name <- 'regression')
  observeEvent(input$correlation, task$name <- 'correlation')

  output$alloutput <- renderPrint({
    task$name
    isolate(
      switch(task$name, 'structure'=viewStructure(), 'regression'=doRegression(), 'correlation'=doCorrelation())
      )
  })

})

Alternatively, you can combine your 3 action buttons into a selectInput and an actions button, so something like:

fluidRow(
  column(6, selectInput('analysis', '', choices=c('View data structure'='structure',
                                                  'Linear regression'='regression',
                                                  'Correlation', 'correlation'))),
  column(6, actionButton('go', 'Go')))

Then modify server.r accordingly.

Yindeng