Reputation: 413
I have a shiny application which reads in multiple csv/txt files, combines them into a list and reactively outputs the data table of the selected file. See below.
library(DT)
library(shiny)
library(data.table)
ui <- fluidPage(sidebarLayout(
sidebarPanel(
fileInput(
"files",
"Choose File",
multiple = TRUE,
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".dp_txt",
".is_txt"
)
),
selectizeInput(
inputId = "selected_table",
label = "Table Selection",
choices = NULL,
selected = NULL,
multiple = FALSE
)
),
mainPanel(DTOutput("table"))
))
server <- function(input, output, session) {
observeEvent(input$files, {
freezeReactiveValue(input, "selected_table")
updateSelectizeInput(session,
inputId = "selected_table",
choices = input$files$name,
server = TRUE)
})
table_list <- reactive({
req(input$files)
setNames(lapply(input$files$datapath, function(x) {
fread(x)
}),
input$files$name)
})
output$table <- renderDT({
req(table_list(), input$selected_table)
table_list()[[input$selected_table]]
}, server = FALSE)
}
shinyApp(ui, server)
However, I want to take the raw data-frames within the list through ~20 transformations (the same transformations for each data frame) prior to outputting the selected data table. I would like to do this for all of the data tables not just one I am outputting as I plan to make a summary tab. I will also need to do things like make new lists from the original list during this data processing.
As a basic example lets say I want to start by removing the first two rows from every data-frame within my list prior to outputting the selected table using something like lapply(list_of_df, function(x) as.data.frame(x[-c(1,2),]))
. How would I go about doing this with the shiny app example given above?
Upvotes: 1
Views: 437
Reputation: 33580
We can simply add another reactive
which is based on the table_list
.
Here the first column is dropped:
library(DT)
library(shiny)
library(data.table)
# create dummy CSVs -------------------------------------------------------
DF1 <- data.frame(x = 1:3, y = letters[1:3])
DF2 <- data.frame(x = 4:6, y = letters[4:6])
DF3 <- data.frame(x = 7:9, y = letters[7:9])
DF4 <- data.frame(x = 10:12, y = letters[10:12])
mapply(
write.csv,
x = list(DF1, DF2, DF3, DF4),
file = list("DF1.csv", "DF2.csv", "DF3.csv", "DF4.csv"),
row.names = FALSE
)
# shiny app ---------------------------------------------------------------
ui <- fluidPage(sidebarLayout(
sidebarPanel(
fileInput(
"files",
"Choose File",
multiple = TRUE,
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".dp_txt",
".is_txt"
)
),
selectizeInput(
inputId = "selected_table",
label = "Table Selection",
choices = NULL,
selected = NULL,
multiple = FALSE
)
),
mainPanel(DTOutput("table"),
DTOutput("filtered_table"))
))
server <- function(input, output, session) {
observeEvent(input$files, {
freezeReactiveValue(input, "selected_table")
updateSelectizeInput(session,
inputId = "selected_table",
choices = input$files$name,
server = TRUE)
})
table_list <- reactive({
req(input$files)
setNames(lapply(input$files$datapath, function(x) {
fread(x)
}),
input$files$name)
})
filtered_table_list <- reactive({
req(table_list())
lapply(table_list(), function(DT) {
DT[, -c(1)]
})
})
output$table <- renderDT({
req(table_list(), input$selected_table)
table_list()[[input$selected_table]]
}, server = FALSE)
output$filtered_table <- renderDT({
req(filtered_table_list(), input$selected_table)
filtered_table_list()[[input$selected_table]]
}, server = FALSE)
}
shinyApp(ui, server)
PS: If not yet done, check out library(data.table) for fast and memory efficient data manipulation:
https://cran.r-project.org/web/packages/data.table/vignettes/datatable-intro.html
https://s3.amazonaws.com/assets.datacamp.com/blog_assets/datatable_Cheat_Sheet_R.pdf
Upvotes: 1