Kevin Tracey
Kevin Tracey

Reputation: 314

How can values of a datatable be replaced in R shiny

I am creating a simple R shiny app where the user uploads a .CSV file and it renders the data table in the main panel, as well as highlights column names automatically in the 'select column' section.

What I am looking for is:

How can values be replaced? (from old to new values). as an example How should I modify the value 100 to 500 in the 'range' column by referencing the column name in the 'select column'?

Note: I have also included a textInput box to mention the old and new values.

csv data

ID  Type  Category    Range
21  A1     B1          100
22  C1     D1          200
23  E1     F1          300

app.R

library(shiny)
library(shinydashboard)
library(reshape2)
library(DT)



ui <- dashboardPage(
  dashboardHeader(title = "Basic dashboard"),
  dashboardSidebar(),
  dashboardBody(
    fluidRow(
      fileInput("file1","Uplaod Data",buttonLabel = "Browse..",placeholder = "No file Selected"),
      checkboxInput("header", "Header", TRUE),
      #actionButton("Splitcolumn", "SplitColumn"),
      selectInput(inputId='selectcolumn', label='select column', ''),
      #actionButton("deleteRows", "Delete Rows"),
      textInput('oldvalue', label='Oldvalue'),
      textInput('newvalue', label='New value to replace')
    ),
    mainPanel(
      DTOutput("table1"),
   
    
  ),
  
  )
)

server <- function(session, input, output) {
  rv <- reactiveValues(data = NULL)
  
  observeEvent(input$file1, {
    file <- input$file1
    ext <- tools::file_ext(file$datapath)
    
    req(file)
    
    validate(need(ext == "csv", "Please upload a csv file"))
    
    rv$data <- read.csv(file$datapath, header = input$header)
    
    updateSelectInput(session, 'selectcolumn', 'select column', names(rv$data))
    
  })
  
  observeEvent(input$Splitcolumn, {
    rv$data <- splitColumn(rv$data, input$selectcolumn)
  })
  
  observeEvent(input$deleteRows,{
    if (!is.null(input$table1_rows_selected)) {
      rv$data <- rv$data[-as.numeric(input$table1_rows_selected),]
    }
  })
  
  output$table1 <- renderDT({
    rv$data
  })
}

shinyApp(ui, server)

Upvotes: 1

Views: 425

Answers (1)

thothal
thothal

Reputation: 20329

The following simplified code does what you want:

library(shiny)
library(DT)
library(dplyr)

ui <- fluidPage(
   sidebarLayout(
      sidebarPanel(
         selectInput("col", "Column to search:", names(mtcars), names(mtcars)[1]),
         textInput("old", "Replace:"),
         textInput("new", "By:"),
         actionButton("replace", "Replace!"),
      ),
      mainPanel(
         DTOutput("table1")
      )
   )
)

server <- function(input, output, session) {
   my_data <- reactiveVal(mtcars)
   
   observeEvent(input$replace, {
      req(input$col)
      dat <- my_data()
      traf <- if (is.numeric(dat[[input$col]])) as.numeric else identity
      my_data(dat %>%
                 mutate(!!rlang::sym(input$col) := 
                           replace(!!rlang::sym(input$col),
                                   as.character(!!rlang::sym(input$col)) == input$old,
                                   input$new) %>% 
                           traf()))
   })
   
   output$table1 <- renderDT(
      my_data()
   )
}

shinyApp(ui, server)

Some remarks are in order:

  • I added a actionButton to allow for triggering the replacement
  • I removed the upload bit, b/c it is not essential to the problem at hand (in the final app, simply assign the uploded data to my_data)
  • I used replace to do the actual replacement (there ar eother options). Thus I transformed to data first to a character vector. If it was numeric before, I re-transform the value. There are other data types not considered yet, so some thought should go into the actuaöl replacement funciton to be as versatile as needed.

Upvotes: 1

Related Questions