如何替换数据表中值的单个组件?

How can I replace a single component of a value in a Datatable?

我正在尝试在 R shiny 应用程序中用 100,066,008,100,066,008 替换变量“030,066,008,030,066,008”。目前,它没有。当我替换所有值时,它起作用了。

重要提示:我只想替换部分值,而不是全部值。

有人可以帮我解决这个问题吗?

CSV 数据

ID  Type  Category    values
21  A1     B1          030,066,008,030,066,008
22  C1     D1          020,030,075,080,095,100
23  E1     F1          030,085,095,060,201,030

App.R

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

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV File", accept = ".csv"),
      checkboxInput("header", "Header", TRUE),
      selectInput("col", "Column to search:", NULL),
      textInput("old", "Replace:"),
      textInput("new", "By:"),
      actionButton("replace", "Replace!"),
    ),
    mainPanel(
      DTOutput("table1")
    )
  )
)

server <- function(input, output, session) {
  my_data <- reactiveVal(NULL)
  
  observeEvent(input$file1, {
    file <- input$file1
    ext <- tools::file_ext(file$datapath)
    req(file)
    validate(need(ext == "csv", "Please upload a csv file"))
    my_data(read.csv(file$datapath, header = input$header))
    updateSelectInput(session, "col", choices = names(my_data()))
  })
  
  observeEvent(input$replace, {
    req(input$col)
    dat <- req(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(
    req(my_data())
  )
}

shinyApp(ui, server)

一个可能的解决方案使用 stringr。我刚刚从 stringr 包中通过 str_replace_all 更改了 replace 函数。

编辑:您可以使用正则表达式作为检测模式,以指定您要检测的确切数字,而不是它是否是另一个数字的一​​部分。

示例:str_replace_all("0300", "030", "100") 将 return 1000 而 str_replace_all("0300", my_regex("030"), "100") 将 return 0300,使用 my_regex 一个正则表达式来指定您想要的确切模式(我必须承认我现在还没有要使用的正则表达式...)

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

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV File", accept = ".csv"),
      checkboxInput("header", "Header", TRUE),
      selectInput("col", "Column to search:", NULL),
      textInput("old", "Replace:"),
      textInput("new", "By:"),
      actionButton("replace", "Replace!"),
    ),
    mainPanel(
      DTOutput("table1")
    )
  )
)

server <- function(input, output, session) {
  my_data <- reactiveVal(NULL)
  
  observeEvent(input$file1, {
    file <- input$file1
    ext <- tools::file_ext(file$datapath)
    req(file)
    # validate(need(ext == "csv", "Please upload a csv file"))
    my_data(read.csv2(file$datapath, header = input$header))
    updateSelectInput(session, "col", choices = names(my_data()))
  })
  
  observeEvent(input$replace, {
    req(input$col)
    dat <- req(my_data())
    traf <- if (is.numeric(dat[[input$col]])) as.numeric else identity

    my_data(dat %>%
              mutate(!!rlang::sym(input$col) := 
                       stringr::str_replace_all(!!rlang::sym(input$col),
                               input$old,
                               input$new) %>% 
                       traf()))
  })
  
  output$table1 <- renderDT(
    req(my_data())
  )
}

shinyApp(ui, server)

我假设您想按列和按行过滤数据集,并假设行值始终是 ID(如果不是,您可以为此添加另一个 selectInput)

注意:使用 stringr::str_replace_all 实际上更聪明,但由于我用了整个下午,我还是想 post 我的解决方案...

注意 2:stringr::str_replace_all 不会用 10000 替换值 03000 吗?不错,那我的方案更好!

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

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV File", accept = ".csv"),
      checkboxInput("header", "Header", TRUE),
      textInput("row", "Select row by ID:"),
      selectInput("col", "Column to search:", NULL),
      textInput("old", "Replace:", value="030"),
      textInput("new", "By:", value ="100"),
      actionButton("replace", "Replace!"),
    ),
    mainPanel(
      DTOutput("table1")
    )
  )
)

server <- function(input, output, session) {
  ## two reactVal, one for the dataset and another for the vector with new values
  my_data <- reactiveVal(NULL)
  vector1 <- reactiveVal(NULL)
  
  observeEvent(input$file1, {
    file <- input$file1
    ext <- tools::file_ext(file$datapath)
    req(file)
    validate(need(ext == "csv", "Please upload a csv file"))
    my_data(read.csv(file$datapath, header = input$header))
    updateSelectInput(session, "col", choices = names(my_data()))
  })
  
  observeEvent(input$replace, {
    req(input$col, input$row, input$new, input$old)
    my_data <- my_data()
    old <- input$old
    new <- input$new
    col1 <- input$col
    row1 <- input$row
    ## create a new vector by:
    vector1(
      my_data %>%
        filter(ID == row1) %>%            ## 1. filtering by row
        select(all_of(col1)) %>%          ## 2. selecting column
        stringr::str_split(",") %>%       ## 3. creating a list of values separated by ','
        unlist() %>%                      ## 4. unlisting the values into a vector of values
        replace(., . == old, new)  %>%    ## 5. changing old values for new values
        paste0(collapse = ",")            ## 6. colapsing all values of vector with ','
    )
    ## replace that vector in the dataframe
    my_data <-  my_data %>% 
      mutate(values = ifelse(ID == row1, vector1(), values))
    
    my_data(my_data)
    
  })
  
  output$table1 <- renderDT(
    req(my_data())
  )
}

shinyApp(ui, server)