Reputation: 383
My shiny app renders a dynamic data frame using the DT
library. User can select the desired rows by clicking. Once the rows are selected the app displays and download the transposed rows in the form of the data frame. However, in doing so (displays and download) I encounter an error as follows-
Error
Warning: Error in [.data.frame: undefined columns selected [No stack trace available]
Here are the steps in details
actionButton()
to mark them as the 'first group'row.names()
.Reproducible code with added comments
library(shiny)
library(DT)
temp_func <- function(){
x <- mtcars
y = x[,1]
return(list(complete_df = as.data.frame(x), column1 = as.data.frame(y)))
}
clean <- function(df, g1, g2){
x1 <- (mtcars)
df_g1 <- subset(df, select = as.vector(g1))
df_g2 <- subset(df, select = as.vector(g2))
df_new <- cbind(df_g1, df_g2)
return(as.data.frame(df_new))
}
# UI
ui <- shinyUI({
fluidPage(
actionButton("fetch", label = "Step1-Fetch data first"),
DT::dataTableOutput("table"),br(),
tags$h5("Selected for Group-1"), verbatimTextOutput("Group1"),br(),
tags$h5("Selected for Group-2"),verbatimTextOutput("Group2"),hr(),br(),
tags$h4("Follow Steps: "),
actionButton("selG1", label = "Step-2: Mark as Group-1"),
actionButton("clear", label = "Step-3: Clear Selection"),
actionButton("selG2", label = "Step-4: Mark as Group-2"),
actionButton("cleanIt", "Step-5: Clean Dataframe"),
DT::dataTableOutput("table2"),
downloadButton("down", "Step-6: Download cleaned dataframe")
)})
# Server
server <- Main_Server <- function(input,output,session){
# Reactive Values
values <- reactiveValues(table = NULL)
group1 <- reactiveValues(Group1 = NULL)
group2 <- reactiveValues(Group2 = NULL)
clean_df <- reactiveValues(df = NULL)
# fetchEvent (Consider temp_func() is fetching data from website)
observeEvent(input$fetch, {values$table <- temp_func()})
# Rendering table for display
output$table <- renderDT({datatable(values$table$complete_df)})
# Selection Event (Gorup1)
observeEvent(input$selG1, {group1$Group1 <- rownames(values$table$complete_df[as.numeric(input$table_rows_selected),])})
# Reset selections
observeEvent(input$clear, {output$table <- renderDT({datatable(values$table$complete_df)})})
# Selection Event (Gorup1)
observeEvent(input$selG2, {group2$Group2 <- rownames(values$table$complete_df[as.numeric(input$table_rows_selected),])})
# Print Events
output$Group1 <- renderPrint({group1$Group1})
output$Group2 <- renderPrint({group2$Group2})
# observeEvent
observeEvent(input$cleanIt, {clean_df$df <- clean(values$table$complete_df, group1$Group1, group2$Group2)
})
# Rendering table for display
output$table2 <- renderDT({datatable(clean_df$df$df_new)})
# Combined Download
output$down <- downloadHandler(
filename = function() { "File.csv"},
content = function(file) {write.csv(clean_df$df$df_new, file)})
}
# Run-app
shinyApp(ui, server)
Upvotes: 1
Views: 467
Reputation: 10365
Your subsetting was wrong; g1
and g2
are rownames, but you used it in subset
which expects columnnames (therefore the error message you've got). Therefore I've changed the clean
function. Your error message is not very informative because you don't have a stack trace. If you want to get a stack trace, you should use the Shiny App template in RStudio (see here at the end of 6.2.1). With this, I get
Warnung: Error in [.data.frame: undefined columns selected
78: stop
77: [.data.frame
75: subset.data.frame
73: clean [C:\Users\jhage\Documents\Programmierung\Shiny_tests\app_2\shinytest7/app.R#12]
72: observeEventHandler [C:\Users\jhage\Documents\Programmierung\Shiny_tests\app_2\shinytest7/app.R#63]
1: runApp
so it's easier to debug.
The corrected code:
library(shiny)
library(DT)
temp_func <- function(){
x <- mtcars
y = x[,1]
return(list(complete_df = as.data.frame(x), column1 = as.data.frame(y)))
}
clean <- function(df, g1, g2){
df_selection <- df[c(which(rownames(df) == g1), which(rownames(df) == g2)), ]
df_new <- t(df_selection)
return(as.data.frame(df_new))
}
# UI
ui <- shinyUI({
fluidPage(
actionButton("fetch", label = "Step1-Fetch data first"),
DT::dataTableOutput("table"),br(),
tags$h5("Selected for Group-1"), verbatimTextOutput("Group1"),br(),
tags$h5("Selected for Group-2"),verbatimTextOutput("Group2"),hr(),br(),
tags$h4("Follow Steps: "),
actionButton("selG1", label = "Step-2: Mark as Group-1"),
actionButton("clear", label = "Step-3: Clear Selection"),
actionButton("selG2", label = "Step-4: Mark as Group-2"),
actionButton("cleanIt", "Step-5: Clean Dataframe"),
DT::dataTableOutput("table2"),
downloadButton("down", "Step-6: Download cleaned dataframe")
)})
# Server
server <- Main_Server <- function(input,output,session){
# Reactive Values
values <- reactiveValues(table = NULL)
group1 <- reactiveValues(Group1 = NULL)
group2 <- reactiveValues(Group2 = NULL)
clean_df <- reactiveValues(df = NULL)
# fetchEvent (Consider temp_func() is fetching data from website)
observeEvent(input$fetch, {values$table <- temp_func()})
# Rendering table for display
output$table <- renderDT({datatable(values$table$complete_df)})
# Selection Event (Gorup1)
observeEvent(input$selG1, {group1$Group1 <- rownames(values$table$complete_df[as.numeric(input$table_rows_selected),])})
# Reset selections
observeEvent(input$clear, {output$table <- renderDT({datatable(values$table$complete_df)})})
# Selection Event (Gorup1)
observeEvent(input$selG2, {group2$Group2 <- rownames(values$table$complete_df[as.numeric(input$table_rows_selected),])})
# Print Events
output$Group1 <- renderPrint({group1$Group1})
output$Group2 <- renderPrint({group2$Group2})
# observeEvent
observeEvent(input$cleanIt, {clean_df$df <- clean(values$table$complete_df, group1$Group1, group2$Group2)
})
# Rendering table for display
output$table2 <- renderDT({datatable(clean_df$df$df_new)})
# Combined Download
output$down <- downloadHandler(
filename = function() { "File.csv"},
content = function(file) {write.csv(clean_df$df$df_new, file)})
}
# Run-app
shinyApp(ui, server)
BTW: Have a look at the selection
argument of datatable
, you can set it so that only one row can be selected, then you don't need the "undo" buttons in your app.
Upvotes: 1