rshinyrecord-linkage

r shiny - display multiple data tables on a page


I am trying to create an app in R shiny. The first thing I would like to do is select two csv files to display on a page. According to this: https://community.rstudio.com/t/creating-tables-in-r-shiny-dynamically/14586 I need to add a dataTableOutput for each table in the UI and another renderDataTable in my server. However, the app doesn't work when I tried that.

The code below only allows the user to load ONE csv file.

X <- c("plyr", "dplyr", "tm", "wordcloud", "SnowballC", "stringdist", "tidytext",
   "rmarkdown", "knitr", "quanteda", "qdap", "reshape", "stringr", "RecordLinkage", 
   "data.table", "rvest", "shiny", "shinydashboard", "DT")
lapply(X, FUN = function(X){
  do.call("library", list(X))
})

UI

ui <- dashboardPage(
  dashboardHeader(title = "Record Linkage App"),
  dashboardSidebar(
    sidebarMenu(
  ## Tab 1 -- Specify Task
  menuItem("Select Task And Upload Files", tabName = "task", icon = icon("file-text-o")),
  ## Tab 2 -- View Raw Data Files
  menuItem("View Raw Data", tabName = "raw", icon = icon("file-text-o")),
  ## Tab 3 -- View Processed Data Files
  menuItem("View Processed Data", tabName = "processed", icon = icon("file-text-o")),
  ## Tab 4 -- Select Training Set
  menuItem("Select Training Set", tabName = "mltrain", icon = icon("file-text-o")),
  ## Tab 5 -- View Weight & Probabilities (choose which chart to view or both?)
  menuItem("Visualize Distributions", tabName = "distributions", icon = icon("bar-chart-o")),
  ## Tab 6 -- View Results (review, match and trash files--need to be able to choose dataset)
  ## Want to be able to add checkboxes to select rows for inclusion in deletion later on
  menuItem("View Result Files", tabName = "fileview", icon = icon("file-text-o"))

)), # close dashboard sidebar

  #### Dashboard Body starts here

  dashboardBody(
    tabItems(
  ### Specify Task & Upload Files Tab
  tabItem(tabName = "task",
          radioButtons("task", "Select a Task:", c("Frame Deduplication", "Frame Record Linkage")),
          fileInput("selection", "Upload Files:", multiple = T, 
                    accept = c(".xls", "text/csv", "text/comma-separated-values, text/plain", ".csv")),
          helpText(paste("Please upload a file.  Supported file types are:  .txt, .csv and .xls.")),
          helpText(paste("Note:  Record Linkage requires two data frames."))

          ), # close first tabItem

  tabItem(tabName = "raw",
          helpText(paste("This tab displays the raw, unprocessed data frames selected in the previous tab.")),
          helpText(paste("Select the columns you wish to display.  These columns will be used for string comparisons")),
            dataTableOutput("contents"),
            dataTableOutput("contents")
          )

) # close tabItems
  ) # close dashboardBody
) #close dashboardpage
options(shiny.maxRequestSize = 100*1024^2)

SERVER

server <- function(input, output, session) {
  output$contents <- renderDataTable({
    req(input$selection)
    #browser()
    read.csv(input$selection$datapath)

  })

  output$contents <- renderDataTable({
req(input$selection)
#browser()
read.csv(input$selection$datapath)

  })

}

shinyApp(ui, server)

I would like to:

  1. Be able to upload multiple files
  2. Choose the columns from each file to display (checkboxInput?)

Any help would be truly appreciated.


Solution

  • I made some changes to your code. Instead of checkboxInput I opted for the pickerInput from the shinyWidgets package (I added that to your code). Displaying two tables on the same page is already a lot of content, adding checkboxInputs on top of that would take up even more space. The pickerInput is light weight and nice and easy to use.

    It is working here, please check it out and let me know if you have any trouble.

    You probably need to configure how you want CSVs to be read in, especially the sep argument.

    Note that reading multiple files with fileInput doesn't work in the RStudio pane or old Browsers such as IE 9.

    Update: now allows to read in excel files with readxl and arranges the two table in columns next to each other.

    X <- c("plyr", "dplyr", "tm", "readxl", "wordcloud", "SnowballC", "stringdist", "tidytext",
               "rmarkdown", "knitr", "quanteda", "reshape", "stringr", "RecordLinkage", 
               "data.table", "rvest", "qdap", "shiny", "shinydashboard", "shinyWidgets", "DT") 
    
    lapply(X, FUN = function(X){
          do.call("library", list(X))
    })
    
    ui <- dashboardPage(
        dashboardHeader(title = "Record Linkage App"),
        dashboardSidebar(
            sidebarMenu(
                ## Tab 1 -- Specify Task
                menuItem("Select Task And Upload Files", tabName = "task", icon = icon("file-text-o")),
                ## Tab 2 -- View Raw Data Files
                menuItem("View Raw Data", tabName = "raw", icon = icon("file-text-o")),
                ## Tab 3 -- View Processed Data Files
                menuItem("View Processed Data", tabName = "processed", icon = icon("file-text-o")),
                ## Tab 4 -- Select Training Set
                menuItem("Select Training Set", tabName = "mltrain", icon = icon("file-text-o")),
                ## Tab 5 -- View Weight & Probabilities (choose which chart to view or both?)
                menuItem("Visualize Distributions", tabName = "distributions", icon = icon("bar-chart-o")),
                ## Tab 6 -- View Results (review, match and trash files--need to be able to choose dataset)
                ## Want to be able to add checkboxes to select rows for inclusion in deletion later on
                menuItem("View Result Files", tabName = "fileview", icon = icon("file-text-o"))
    
            )), # close dashboard sidebar
    
        #### Dashboard Body starts here
    
        dashboardBody(
            tabItems(
                ### Specify Task & Upload Files Tab
                tabItem(tabName = "task",
                        radioButtons("task", "Select a Task:", c("Frame Deduplication", "Frame Record Linkage")),
                        fileInput("selection", "Upload Files:", multiple = T, 
                                  accept = c(".xlsx", ".xls", "text/csv", "text/comma-separated-values, text/plain", ".csv")),
                        helpText(paste("Please upload a file.  Supported file types are:  .txt, .csv and .xls.")),
                        helpText(paste("Note:  Record Linkage requires two data frames."))
    
                ), # close first tabItem
    
                tabItem(tabName = "raw",
                        helpText(paste("This tab displays the raw, unprocessed data frames selected in the previous tab.")),
                        helpText(paste("Select the columns you wish to display.  These columns will be used for string comparisons")),
                        fluidRow(
                            column(width = 6,
                                   uiOutput("pick_col1"),
                                   dataTableOutput("content1")
                                   ),
                            column(width = 6,
                                   uiOutput("pick_col2"),
                                   dataTableOutput("content2")
                                   )
                        )
    
            ) # close tabItem
        ) # close tabItems
    ) # close dashboardBody 
    ) # closes dashboardpage
    options(shiny.maxRequestSize = 100*1024^2)
    
    
    server <- function(input, output, session) {
    
        data <- reactiveValues(file1 = NULL,
                               file2 = NULL)
    
        observe({
            if (!is.null(input$selection$datapath[1]))
    
                if (grepl(".csv$", input$selection$datapath[1])) {
    
                    data$file1 <- read.csv(input$selection$datapath[1], header = TRUE, sep = ";")
    
                } else if (grepl(".xls$|.xlsx$", input$selection$datapath[1])) {
    
                    data$file1 <- read_excel(input$selection$datapath[1], col_names = TRUE)    
                } 
        })
    
        observe({
            if (!is.null(input$selection$datapath[2]))
    
                if (grepl(".csv$", input$selection$datapath[2])) {
    
                    data$file2 <- read.csv(input$selection$datapath[2], header = TRUE, sep = ";")
    
                } else if (grepl(".xls$|.xlsx$", input$selection$datapath[2])) {
    
                    data$file2 <- read_excel(input$selection$datapath[2], col_names = TRUE)    
                } 
        })
    
        output$pick_col1 <- renderUI({
    
            pickerInput(
                inputId = "pick_col1",
                label = "Select the columns of table 1 you wish to display:",
                choices = colnames(data$file1),
                selected = colnames(data$file1),
                options = list(`actions-box` = TRUE,
                               `selected-text-format` = paste0("count > ", length(colnames(data$file1)) - 1),
                               `count-selected-text` = "Alle",
                               liveSearch = TRUE,
                               liveSearchPlaceholder = TRUE),   # build buttons for collective selection
                multiple = TRUE)
        })
    
        output$pick_col2 <- renderUI({
    
            pickerInput(
                inputId = "pick_col2",
                label = "Select the columns of table 2 you wish to display:",
                choices = colnames(data$file2),
                selected = colnames(data$file2),
                options = list(`actions-box` = TRUE,
                               `selected-text-format` = paste0("count > ", length(colnames(data$file2)) - 1),
                               `count-selected-text` = "Alle",
                               liveSearch = TRUE,
                               liveSearchPlaceholder = TRUE),   # build buttons for collective selection
                multiple = TRUE)
        })
    
    
    
        output$content1 <- renderDataTable({
    
            data$file1[, req(input$pick_col1)]
    
    
        })
    
        output$content2 <- renderDataTable({
    
            data$file2[, req(input$pick_col2)]
    
        })
    
    }
    
    shinyApp(ui, server)