0

I am making a shiny where I can read a CSV file, and then be able to replace a selected column with a new value (which in this case replaced by 0).
I usually use a mutate function to do this.

How to use mutate function properly in shiny, when the selected column is also an input?

ui <- fluidPage(fileInput('file1', h2('Dataset Settings'),
                          accept=c('text/csv', 'text/comma-separated-values,text/plain', '.csv')),
                tags$hr(),
                
                selectInput(inputId = "replaceCol",
                            label = "Select numeric with missing value",
                            choices = c()),
                actionButton(inputId = "confirm", 
                             label = "Replace with 0"),
                tags$hr(),
                dataTableOutput("Original")
)
  



server <- function(input, output, session){

  data_set <- reactive({
    inFile <- input$file1
    read.csv(inFile$datapath)
  })
  
  observe({
    req(input$file1)
    temp <- colnames(data_set())
    col <- list()
    col[temp] <- temp
    updateSelectInput(session,
                      inputId = "replaceCol",
                      choices = col,
                      selected = "")
  })
  
  output$Original <- renderDataTable({
    data_set()
  })

  
  observeEvent(input$confirm,{
    data_set() <- mutate(data_set(), replace(input$replaceCol, TRUE, 0))
  })
  
}

shinyApp(ui = ui, server = server)
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83

1 Answers1

1

Your code has several issues:

  • if a UI element depends on some calculation from the server, it is best to use renderUI
  • you can't directly assign something to the output of a reactive function
  • if you want to dynamically generate variable names in dplyr, it's a bit more complicated

Therefore, I use a reactiveVal to store your dataset and update it, if a column is changed. I'm not completely satisfied with the use of an observer to update the data_set() when a new file is chosen, I'm happy to hear if someone has a better solution.

library(shiny)
library(dplyr)

ui <- fluidPage(fileInput('file1', h2('Dataset Settings'),
                          accept=c('text/csv', 'text/comma-separated-values,text/plain', '.csv')),
                tags$hr(),
                
                uiOutput(outputId = "UI_replaceCol"),
                actionButton(inputId = "confirm", 
                             label = "Replace with 0"),
                tags$hr(),
                dataTableOutput("Original")
)




server <- function(input, output, session){
  
  # reactive variable to store the data
  data_set <- reactiveVal()
  
  observeEvent(input$file1, {
    inFile <- input$file1
    data <- read.csv(inFile$datapath)
    data_set(data)
  })
  
  output$UI_replaceCol <- renderUI({
    req(data_set())
    col <- colnames(data_set())
    selectInput(inputId = "replaceCol",
                label = "Select numeric with missing value",
                choices = col)
  })
  
  output$Original <- renderDataTable({
    data_set()
  })
  
  
  observeEvent(input$confirm,{
    data <- data_set() %>% 
      mutate(!!as.symbol(input$replaceCol) :=
               replace(!!as.symbol(input$replaceCol), TRUE, 0))
    
    data_set(data)
  })
  
}

shinyApp(ui = ui, server = server)
starja
  • 9,887
  • 1
  • 13
  • 28