Upload a file and make reactive boxplots


#1

Good evening to everyone, I’m building my first application. I would like to be able to upload a file and get boxplots for each variable of the uploaded file. I found this fantastic example but I can not make it work with an external file, I get the error “invalid first argument”. Can someone help me to solve the problem? Thanks so much.

(Example: https://gist.github.com/jcheng5/5929787)

This is my code:

#initialize
library(shiny)
library(datasets)
library(ggplot2) 

#helper function (convert vector to named list)
namel<-function (vec){
  tmp<-as.list(vec)
  names(tmp)<-as.character(unlist(vec))
  tmp
}

# UI for app
ui<-(pageWithSidebar(
  # title
  headerPanel("Select Options"),
  
  #input
  sidebarPanel
  (
    # Input: Select a file ----
    
    fileInput("file1", "Choose CSV File",
              multiple = TRUE,
              accept = c("text/csv",
                         "text/comma-separated-values,text/plain",
                         ".csv")),
    # Input: Checkbox if file has header ----
    checkboxInput("header", "Header", TRUE),
    
    # Input: Select separator ----
    radioButtons("sep", "Separator",
                 choices = c(Semicolon = ";",
                             Comma = ",",
                             Tab = "\t"),
                 selected = ";"),
    # Horizontal line ----
    tags$hr(),
    
    # Input: Select number of rows to display ----
    radioButtons("disp", "Display",
                 choices = c(All = "all",
                             Head = "head"),
                 selected = "all"),
    
    
    # Input: Select what to display
    selectInput("dataset","Data:", 
                list(iris = "iris", mtcars = "mtcars", uploaded_file = "inFile")
    ),
    selectInput("variable","Variable:", "Loading..."),
    selectInput("group","Group:", "Loading..."),
    selectInput("plot.type","Plot Type:", 
                list(boxplot = "boxplot", histogram = "histogram", density = "density", bar = "bar")
    ),
    checkboxInput("show.points", "show points", TRUE)
  ),	
  
  # output				
  mainPanel(
    h3(textOutput("caption")),
    #h3(htmlOutput("caption")),
    uiOutput("plot") # depends on input 
  )
))


# shiny server side code for each call
server<-(function(input, output, session){
  #update variable and group based on dataset
  observe({
    if (is.null(input$dataset))
      return()
    obj<-switch(input$dataset,
                "iris" = iris,
                "mtcars" = mtcars,
                "inFile" = uploaded_file)	 
    var.opts<-namel(colnames(obj))
    updateSelectInput(session, "dataset", choices = var.opts)
    updateSelectInput(session, "variable", choices = var.opts)
    updateSelectInput(session, "group", choices = var.opts)
  })
  
  output$caption<-renderText({
    switch(input$plot.type,
           "boxplot" 	= 	"Boxplot",
           "histogram" =	"Histogram",
           "density" 	=	"Density plot",
           "bar" 		=	"Bar graph")
  })
  
  
  output$plot <- renderUI({
    plotOutput("p")
  })
  
  #plotting function using ggplot2
  output$p <- renderPlot({
    
    variable <- get(input$dataset)[[input$variable]]
    group <- get(input$dataset)[[input$group]]
    if (is.null(variable) || is.null(group))
      return(NULL)
    
    plot.obj<<-list() # not sure why input$X can not be used directly?
    plot.obj$data<<-get(input$dataset) 
    plot.obj$variable<<-with(plot.obj$data,get(input$variable)) 
    plot.obj$group<<-with(plot.obj$data,get(input$group)) 
    
    #dynamic plotting options
    plot.type<-switch(input$plot.type,
                      "boxplot" 	= 	geom_boxplot(),
                      "histogram" =	geom_histogram(alpha=0.5,position="identity"),
                      "density" 	=	geom_density(alpha=.75),
                      "bar" 		=	geom_bar(position="dodge")
    )
    
    require(ggplot2)
    #plotting theme
    .theme<- theme(
      axis.line = element_line(colour = 'gray', size = .75), 
      panel.background = element_blank(),  
      plot.background = element_blank()
    )	 
    if(input$plot.type=="boxplot")	{		#control for 1D or 2D graphs 
      p<-ggplot(plot.obj$data, 
                aes(
                  x 		= plot.obj$group, 
                  y 		= plot.obj$variable,
                  fill 	= as.factor(plot.obj$group)
                )
      ) + plot.type
      
      if(input$show.points==TRUE)
      { 
        p<-p+ geom_point(color='black',alpha=0.5, position = 'jitter')
      }
      
    } else {
      
      p<-ggplot(plot.obj$data, 
                aes(
                  x 		= plot.obj$variable,
                  fill 	= as.factor(plot.obj$group),
                  group 	= as.factor(plot.obj$group)
                  #color 	= as.factor(plot.obj$group)
                )
      ) + plot.type
    }
    
    p<-p+labs(
      fill 	= input$group,
      x 		= "",
      y 		= input$variable
    )  +
      .theme
    print(p)
  })
  # Read file ----
  df <- reactive({
    req(input$file1)
    read.csv(input$file1$datapath,
             header = input$header,
             sep = input$sep)
    
    
    data <- reactive({ 
      req(input$file1) ##  require that the input is available
      
      inFile <- input$file1 
      
      df <- read.csv(inFile$datapath, header = input$header, sep = input$sep,
                     quote = input$quote)
      
      
    })
    
    
  })
  
  
  
})


# Create Shiny app ----
shinyApp(ui, server)


#2

Solved here https://gist.github.com/dgrapov/dfcf6ab2339b1cf19b090cfb8dadc855


#3

HI @Bee,

As you problem is solved, can you mark your question as solved too ?
Discourse has a mechanism for marking question as solved and it will be indicated in the list of question. If someone as the same issue, it will be easier to find answer !

Thanks!


#4

Yes, of course, thanks for explaining!