【问题标题】:extract regex from a column and replace从列中提取正则表达式并替换
【发布时间】:2020-03-06 04:33:05
【问题描述】:

我希望读取一个文件并在 R 中处理它。它遵循以下格式:

tibble(row=8,name="Shawn",state="Arizona", age=45,
comments="father=Alex;NSM;GNO;One:0.9995,0.13|Two:0.9991,0.55|Three:0.9996,0.33|Four:0.9986,0.22|Five:0.9987,0.22")
# A tibble: 1 x 5
        row name  state     age comment                                                                          
      <dbl> <chr> <chr>   <dbl> <chr>                                                                             
    1     8 Shawn Arizona    45 father=Alex;NSM;GNO;One:0.9995,0.13|Two:0.9991,0.55|Three:0.9996,0.33|Four:0.9986…

我想用

替换最后一列
comment
One:0.9995|Two:0.9991|Three:0.9996|Four:0.9986|Five:0.9987

然后用1减去浮点数:

comment
One:0.0005|Two:0.0009|Three:0.0004|Four:0.0014|Five:0.0013

【问题讨论】:

    标签: r regex dplyr


    【解决方案1】:

    此函数不是特别高效或优雅,但它会为您提供您所要求的输出。它不是矢量化的,但您可以使用sapply 来解决这个问题。

    sample <- "father=Alex;NSM;GNO;One:0.9995,0.13|Two:0.9991,0.55|Three:0.9996,0.33|Four:0.9986,0.22|Five:0.9987,0.22"
    
    extract_numbers <- function(x) {
      x <- sub(".*;", "", x)
      x <- gsub(",([0-9.]*)|", "", x)
      x <- strsplit(x, "|", fixed = TRUE)[[1]]
      do.call(
        "paste", 
        c(
          lapply(
            strsplit(x, ":"), 
            function(y) paste(y[1], sprintf("%6.4f", 1 - as.numeric(y[2])), sep = ":")
          ),
          sep = "|"
        )
      )
    }
    
    extract_numbers(sample)
    # [1] "One:0.0005|Two:0.0009|Three:0.0004|Four:0.0014|Five:0.0013"
    

    【讨论】:

      【解决方案2】:

      我们可以使用tidyverse 解决这个问题。我们首先使用gsub 删除直到最后一个分号和数字后跟逗号的字符。我们将"|" 上的行拆分为单独的行,然后将":" 上的行拆分为不同的列,然后从 1 中减去该值。

      library(dplyr)
      library(tidyr)
      
      df %>%
        mutate(comments = gsub(".*;|,\\d\\.\\d+", "", comments)) %>%
        separate_rows(comments, sep = "\\|") %>%
        separate(comments, into = c('num', 'value'), sep = ":", convert = TRUE) %>%
        mutate(value = 1 - value)
      
      # A tibble: 5 x 6
      #    row name  state     age num      value
      #  <dbl> <chr> <chr>   <dbl> <chr>    <dbl>
      #1     8 Shawn Arizona    45 One   0.000500
      #2     8 Shawn Arizona    45 Two   0.0009  
      #3     8 Shawn Arizona    45 Three 0.000400
      #4     8 Shawn Arizona    45 Four  0.00140 
      #5     8 Shawn Arizona    45 Five  0.00130 
      

      如果需要再次作为汇总值,我们可以添加到链中

      %>% group_by(row, name, state, age) %>%
          summarise(comments = paste(num, round(value, 5), collapse = "|", sep = ":"))
      
      #   row name  state     age comments                                                  
      #  <dbl> <chr> <chr>   <dbl> <chr>                                                     
      #1     8 Shawn Arizona    45 One:0.0005|Two:0.0009|Three:0.0004|Four:0.0014|Five:0.0013
      

      【讨论】:

        【解决方案3】:

        你可以像这样使用data.table中的strsplittstrsplit(打电话给你的桌子DT):

        library(data.table)
        setDT(DT)
        
        DT = DT[ , c(.SD, tstrsplit(comments, ';', fixed = TRUE))]
        DT = DT[ , strsplit(V9, '|', fixed = TRUE), by = row]
        DT[ , c('key', 'val1', 'val2') := tstrsplit(V1, '[:,]', type.convert = TRUE)]
        DT[ , val1 := 1-val1][]
        #      row                V1    key   val1  val2
        # 1:     8   One:0.9995,0.13    One 0.0005  0.13
        # 2:     8   Two:0.9991,0.55    Two 0.0009  0.55
        # 3:     8 Three:0.9996,0.33  Three 0.0004  0.33
        # 4:     8  Four:0.9986,0.22   Four 0.0014  0.22
        # 5:     8  Five:0.9987,0.22   Five 0.0013  0.22
        

        tstrsplit 执行strsplit,然后执行transpose——这将输入字符串x 转换为一列,用于split 的每个结果x 的每个元素。

        在第二步中,我假设row 是每一行的唯一标识符。如果有很多 rows,这可能会很慢 - 您可以尝试 here 以获取其他一些方法来将 V9 “取消嵌套”到不同的行中。

        然后我们再次tstrsplit 得到你想要的值作为自己的列;请注意,type.convert 会自动将看起来像数字的列转换为数字(而不是数字作为字符串)。

        如果您希望将数据恢复为原始字符串格式,我们可以将其反转,但使用当前格式的数据会更容易。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-12-10
          • 2019-02-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多