3

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)

2 Answers 2

2

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)
Sign up to request clarification or add additional context in comments.

2 Comments

firstly, thank you so much! this worked well for me and the explanations were useful in understanding your code. apologies for basic errors in the initial code as I'm still learning shiny on the go for this urgent task. I would like to ask, right now this code works for plotting the sum of a Y variable I've specified. What if I want to: 1) allow the user to specify the y variable to sum 2) allow the user to plot the bar chart by count instead of a specific y variable. thank you so much once again!
Don't worry about those "errors" as they were working anyway. I just made your code a bit shorter. Your questions: 1) You might include another input option (e.g. select input) in your graphing-tab-panel and use that variable for summing prior to creating the plot (just include the operations and use the resulting dataframe for the plot). 2) You can use ggplot's stat="count"or you can count the cases e.g. via dplyr n_distinct operation. I pretty sure after a quick websearch you'll easily find what you're looking for.
1

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.

1 Comment

hi msr_003, thank you for your attempt to help! unfortunately I faced a " Error in (function (choice, name) : All sub-lists in "choices" must be named " when attempting to run your code and could not figure out the issue. Also, Alex's answer helped to solve my problem. Nonetheless thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.