Search code examples
rshinyrscriptrshiny

How to add empty column after the specific column and replace the values according to the user specific in R shiny


The buttons "SplitColumns," "DeleteRows," and "Repace values" are shown in the R shiny Code below; according to the code, after uploading the csv data the buttons "SplitColumns" and "DeleteRows" operate flawlessly. To make this even more useful, I'd like to add empty column after the user-specified column(as per SelectInput : labeled: "select column) and replace the values in the box labeled "Input the value to replace:"

I created a function called "fillvalues" for this, however, it does not work and gives me the following error.

Could someone assist me how to fix this issue?

Error

Warning: Error in sub: object 'df_fill' not found

csv data

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

app.R

library(shiny)
library(reshape2)
#source('splitColumn_stack.R')
library(DT)


###function for deleting the rows
splitColumn <- function(data, column_name) {
  newColNames <- c("Unmerged_type1", "Unmerged_type2")
  newCols <- colsplit(data[[column_name]], " ", newColNames)
  after_merge <- cbind(data, newCols)
  after_merge[[column_name]] <- NULL
  after_merge
}
###_______________________________________________
### function for replacing the empty values

library(tidyr)

fillvalues <- function(columName, value){
  df_fill[[columName]] <- sub("^$", value , df_fill[[columName]])
  df_fill
}




### use a_splitme.csv for testing this program

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV File", accept = ".csv"),
      checkboxInput("header", "Header", TRUE),
      actionButton("Splitcolumn", "SplitColumn"),
      selectInput(inputId='selectcolumn', label='select column', ''),
      actionButton("deleteRows", "Delete Rows"),
      textInput("textbox", label="Input the value to replace:"),
      actionButton("replacevalues", label = 'Replace values')
    ),
    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
  })
  observeEvent(input$replacevalues, {
    rv$value <- fillvalues(rv$value, input$selectcolumn)
  })
}

shinyApp(ui, server)

Solution

  • No need to "replace" any values, just insert a new column with values entered by the user.

    Below is an example using the add_column() function from the tibblepackage.

    Be aware that it is just a starting point, where the user must enter the right number of values corresponding to the number of lines in the table, separated by commas.

    There is also no verification of the type of values entered so they all end up as characters in the new column.

    library(shiny)
    library(reshape2)
    #source('splitColumn_stack.R')
    library(DT)
    library(tibble)
    
    
    ###function for deleting the rows
    splitColumn <- function(data, column_name) {
    newColNames <- c("Unmerged_type1", "Unmerged_type2")
    newCols <- colsplit(data[[column_name]], " ", newColNames)
    after_merge <- cbind(data, newCols)
    after_merge[[column_name]] <- NULL
    after_merge
    }
    ###_______________________________________________
    ### function for inserting a new column
    
    fillvalues <- function(data, values, columName){
     df_fill <- data
     vec <- strsplit(values, ",")[[1]]
     df_fill <- tibble::add_column(df_fill, newcolumn = vec, .after = columName)
     df_fill
    }    
    
    ### use a_splitme.csv for testing this program
    
    ui <- fluidPage(
     sidebarLayout(
       sidebarPanel(
       fileInput("file1", "Choose CSV File", accept = ".csv"),
      checkboxInput("header", "Header", TRUE),
      actionButton("Splitcolumn", "SplitColumn"),
      selectInput(inputId='selectcolumn', label='select column', ''),
      actionButton("deleteRows", "Delete Rows"),
      textInput("textbox", label="Input the value to replace:"),
      actionButton("replacevalues", label = 'Replace values')
    ),
    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
    })
    observeEvent(input$replacevalues, {
      rv$data <- fillvalues(rv$data, input$textbox, input$selectcolumn)
    })
    }
    
    shinyApp(ui, server)