Reputation: 413
I have a shiny application where I read in multiple .csv files (dummy .csvs for this example) and store them as a list of data frames which can be selected with a drop down tab. When a file is selected using the drop down tab a table is displayed using renderDT
and a scatter plot using the values in that table is also shown. You can use the dummy csv's created in your directory to try this.
library(DT)
library(shiny)
library(data.table)
# create dummy CSVs -------------------------------------------------------
DF1 <- data.frame(x = 1:3, y = 2:4)
DF2 <- data.frame(x = 4:2, y = 5:7)
DF3 <- data.frame(x = 7:9, y = 8:10)
DF4 <- data.frame(x = 10:8, y = 11:13)
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"), plotOutput("plot"))
))
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)
output$plot <- renderPlot({
temp <- table_list()[[input$selected_table]]
plot(temp$x, temp$y)
})
}
shinyApp(ui, server)
How can I delete rows of data for individual data frames and the corresponding point on the plot? Basically, when a row is deleted I want the row to be deleted on the server side so that any other plots or tables depending on that original table are also updated. Lastly, I want this deletion to remain permanent so that when switching through the different dataframes the rows/points you deleted don't come back when return to that dataframe. How can I do this?
Upvotes: 2
Views: 127
Reputation: 33417
This seems to be a follow-up on my earlier answer here.
Once you need to modify a reactive
in multiple places, we need to use reactiveVal
or reactiveValues
.
Please check the observeEvent(input$deleterow, ...
call:
library(DT)
library(shiny)
library(data.table)
# create dummy CSVs -------------------------------------------------------
DF1 <- data.frame(x = 1:3, y = 2:4)
DF2 <- data.frame(x = 4:2, y = 5:7)
DF3 <- data.frame(x = 7:9, y = 8:10)
DF4 <- data.frame(x = 10:8, y = 11:13)
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"),
actionButton("deleterow", "Delete row(s)"),
plotOutput("plot"))
))
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 <- reactiveVal()
observeEvent(input$files, {
req(input$files)
table_list(setNames(lapply(input$files$datapath, function(x) {
fread(x)
}),
input$files$name))
})
observeEvent(input$deleterow, {
if(!is.null(input$table_rows_selected)){
tmp_table_list <- table_list()
tmp_table_list[[input$selected_table]] <- table_list()[[input$selected_table]][-input$table_rows_selected]
table_list(tmp_table_list)
}
})
output$table <- renderDT({
req(table_list(), input$selected_table)
table_list()[[input$selected_table]]
}, server = FALSE)
output$plot <- renderPlot({
temp <- table_list()[[input$selected_table]]
req(NROW(temp) > 0)
plot(temp$x, temp$y)
})
}
shinyApp(ui, server)
Upvotes: 3