wei
wei

Reputation: 31

R Shiny: read data file, get user to select variable, plot with ggplot

As stated in the title, I'm trying to use Shiny in R to create a program that reads a csv file uploaded by the user, after which the user can select a variable from that file to view a plot that is plotted by ggplot. I'm trying to achieve this over two tabs, the first tab will read the file and the second tab will get the user to select the variable to view the plot.

My codes are as below. Currently, I am able to successfully read the user's file but I am not able to plot based on the variable selected (I currently only have 1 variable "Location" for demo). (HomeWTaxAmt is the y variable to plot against).

library(shiny)
library(ggplot2)
library(data.table)
library(RColorBrewer)
options(scipen=1000)

ui <- fluidPage(
  navbarPage("User Interface:",tabPanel("Upload",
  titlePanel("Uploading Files"),
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV File",
                multiple = TRUE,
                accept = c("text/csv",
                           "text/comma-separated-values,text/plain",
                           ".csv")),
      tags$hr(),
      checkboxInput("header", "Header", TRUE),
      radioButtons("sep", "Separator",
                   choices = c(Comma = ",",
                               Semicolon = ";",
                               Tab = "\t"),
                   selected = ","),
      tags$hr(),
      radioButtons("disp", "Display",
                   choices = c(Head = "head",
                               All = "all"),
                   selected = "head"),
      radioButtons("quote", "Quote",
                   choices = c(None = "",
                               "Double Quote" = '"',
                               "Single Quote" = "'"),
                   selected = '"')),
    mainPanel(
      verbatimTextOutput("summary"),
      tableOutput("contents")
    ))), 
  tabPanel("Graphing",
                 titlePanel("Plotting Graphs"),
                 sidebarLayout(
                   sidebarPanel(
                     selectInput("variable", "Variable:",
                                 list("Location"))),
                   mainPanel(
                     h3(textOutput("caption")),
                     plotOutput("ggplot")
                   )
  ))
))

server <- function(input, output) {
  output$contents <- renderTable({
    req(input$file1)
    library(data.table)
    data <- fread(input$file1$datapath,
                  header = input$header,
                  sep = input$sep,
                  quote = input$quote)

    if(input$disp == "head") {
      return(head(data))
    }
    else {
      return(data)
    }

  })
  output$summary <- renderPrint({
    summary(data)
  })

  formulaText <- reactive(function() {
    paste("HomeWTaxAmt ~", input$variable)
  })

  output$caption <- renderText(function() {
    formulaText()
  })

  output$ggplot <- renderPlot(function() {
    data <- fread(input$file1$datapath,
                  header = input$header,
                  sep = input$sep,
                  quote = input$quote)
    if(is.null(data)) return(NULL)
    # check for the input variable
    ggplot(data, aes(x=reorder(factor(data[input$variable]), -abs(HomeWTaxAmt), function(x){sum(x)}), 
                     weight = abs(HomeWTaxAmt), fill = factor(data[input$variable]))) + geom_bar(show.legend=FALSE) + xlab(input$variable) + 
            scale_fill_manual(values=brewer.pal(n = 12, name = "Paired"))
  })
}

shinyApp(ui, server)

Upvotes: 3

Views: 1702

Answers (2)

msr_003
msr_003

Reputation: 1233

Modified your code a bit and i hope it helps you.

library(shiny)
library(ggplot2)

ui <- fluidPage(
  navbarPage("User Interface:",tabPanel("Upload",
                                        titlePanel("Uploading Files"),
                                        sidebarLayout(
                                          sidebarPanel(
                                            fileInput("file1", "Choose CSV File",
                                                      multiple = TRUE,
                                                      accept = c("text/csv",
                                                                 "text/comma-separated-values,text/plain",
                                                                 ".csv")),
                                            tags$hr(),
                                            checkboxInput("header", "Header", TRUE),
                                            radioButtons("sep", "Separator",
                                                         choices = c(Comma = ",",
                                                                     Semicolon = ";",
                                                                     Tab = "\t"),
                                                         selected = ","),
                                            tags$hr(),
                                            radioButtons("disp", "Display",
                                                         choices = c(Head = "head",
                                                                     All = "all"),
                                                         selected = "head"),
                                            radioButtons("quote", "Quote",
                                                         choices = c(None = "",
                                                                     "Double Quote" = '"',
                                                                     "Single Quote" = "'"),
                                                         selected = '"')),
                                          mainPanel(
                                            verbatimTextOutput("summary"),
                                            tableOutput("contents")
                                          ))), 
             tabPanel("Graphing",
                      titlePanel("Plotting Graphs"),
                      sidebarLayout(
                        sidebarPanel( uiOutput("variable_x"),
                                      uiOutput("variable_y")),
                        mainPanel(
                          h3(textOutput("caption")),
                          plotOutput("plot")
                        )
                      ))
  ))

server <- function(input, output, session) {
  onSessionEnded(stopApp)
  data <- reactive({
    req(input$file1)
    df <- read.csv(input$file1$datapath, header = input$header, sep = input$sep, quote = input$quote)
    return(df)
  })

  output$contents <- renderTable({
    if (input$disp == "head") {
      return(head(data()))
    }
    else {
      return(data())
    }
  })
  output$summary <- renderPrint({
    summary(data())
  })

  output$variable_x <- renderUI({
    selectInput("variableNames_x", label = "Variable_X", choices = names(data()))  
  })
  output$variable_y <- renderUI({
    selectInput("variableNames_y", label = "Variable_Y", choices = names(data()) ) 
  })
  dat <- reactive({
    test <- data.frame(data()[[input$variableNames_x]], data()[[input$variableNames_y]])
    colnames(test) <- c("X", "Y")
    return(test)
  })

  output$plot <- renderPlot({
    if (is.null(data)) { return(NULL)
    } else {
      ggplot(dat(),aes(x = X,y = Y)) + geom_point(colour = 'red',height = 400,width = 600) +
        labs(y = input$variableNames_y,
             x = input$variableNames_x,
             title = "ggplot")
    }
  })
}

shinyApp(ui, server)

Note : I have changed your ggplot function but you can change as per your requirement.

Upvotes: 1

alex_555
alex_555

Reputation: 1102

As I did not have access to your exact .csv files I had to make some adjustments to the plotting command, but I'm pretty sure you can go from there and get it to work with your data. Please note that not loading a .csv file now gives you errors on the first tab, which dissapear as soon as data is loaded. You might want to use some ifelse switches here to ensure the end-user doesn't have to see these R-errors.

Here's the code that plots a plot as intended based on some sample data I had:

library(shiny)
library(ggplot2)
library(data.table)
library(RColorBrewer)
options(scipen=1000)

#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# I didn't change anything in this section
ui <- fluidPage(
  navbarPage("User Interface:",tabPanel("Upload",
                                        titlePanel("Uploading Files"),
                                        sidebarLayout(
                                          sidebarPanel(
                                            fileInput("file1", "Choose CSV File",
                                                      multiple = TRUE,
                                                      accept = c("text/csv",
                                                                 "text/comma-separated-values,text/plain",
                                                                 ".csv")),
                                            tags$hr(),
                                            checkboxInput("header", "Header", TRUE),
                                            radioButtons("sep", "Separator",
                                                         choices = c(Comma = ",",
                                                                     Semicolon = ";",
                                                                     Tab = "\t"),
                                                         selected = ","),
                                            tags$hr(),
                                            radioButtons("disp", "Display",
                                                         choices = c(Head = "head",
                                                                     All = "all"),
                                                         selected = "head"),
                                            radioButtons("quote", "Quote",
                                                         choices = c(None = "",
                                                                     "Double Quote" = '"',
                                                                     "Single Quote" = "'"),
                                                         selected = '"')),
                                          mainPanel(
                                            verbatimTextOutput("summary"),
                                            tableOutput("contents")
                                          ))), 
             tabPanel("Graphing",
                      titlePanel("Plotting Graphs"),
                      sidebarLayout(
                        sidebarPanel(
                          selectInput("variable", "Variable:",
                                      list("Location"))),
                        mainPanel(
                          h3(textOutput("caption")),
                          plotOutput("ggplot")
                        )
                      ))
  ))
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


server <- function(input, output, session) {  # make sure to include "session" here, in order to update your inputs later
  # create an reactive upload to access your data more quickly and easily
  reactive_data <- reactive({
    print(input$file1$datapath)
    data <- fread(input$file1$datapath,
                  header = input$header,
                  sep = input$sep,
                  quote = input$quote)
    return(data)
  })

  # preview
  # no library(data.table) required here, as its already loaded at the beginning of the script)
  output$contents <- renderTable({
    # load your data
    data <- reactive_data()

    if(input$disp == "head") {
      return(head(data))
    }
    else {
      return(data)
    }

  })
  output$summary <- renderPrint({
    summary(reactive_data())
  })

  formulaText <- reactive({ # no need for function() here
    paste("HomeWTaxAmt ~", input$variable)
  })

  output$caption <- renderText({
    formulaText()
  })

  output$ggplot <- renderPlot({

    # load your data
    data <- reactive_data()

    # to only plot when data is not NULL, make sure to include the plotting command in the if-else statement
    # no data
    if(is.null(data)){
      return(NULL)

    }else{
    # data

      # update your selectInput first, so that all the variables match your .csv headers
      updateSelectInput(session, "variable",
                        choices = colnames(data),
                        selected = input$variable) # this keeps the input on the last thing selected on tab-change

      # check for the input variable
      # I used aes_string here so that indexing the colnames works
      # you'll have to adjust the plotting command to your needs as my .csv files aren't the same as yours
      plot <- ggplot(data, aes_string(x=colnames(data)[colnames(data) == input$variable], colnames(data)[length(colnames(data))]))+
        geom_bar(stat="identity")

      # Display your plot
      print(plot)

    }

  })
}

shinyApp(ui, server)

Upvotes: 2

Related Questions