【问题标题】:Separate string column in data.table in multiple columns in R在 R 中的多列中分隔 data.table 中的字符串列
【发布时间】:2020-07-01 11:11:39
【问题描述】:

想象一下,我有一个带有以下字符串列的 R data.table:

string
a1; b: b1, b2, b3; c: c1, c2, c3
a1; b: b2, b3, b4; c: c1, c2, c3; d: d1, d2, d3
a2; b: b1, b2, b3; c: c2, c5, c6; d: d1, d2, d3; e: e2, e3, e4 
a5; b: b5, b6, b7; c: c1, c2, c3; d: d1, d2, d3
a6; b: b1, b2, b3; c: c1, c4, c5; d: d1, d2, d3; e: e1, e2, e3; f: f1, f2, f3

我想用分号分隔每个字符串并将其写入新列 (a, b, c, d, e, f),如下所示:

a   b           c           d           e           f
a1  b1, b2, b3  c1, c2, c3  NA          NA          NA
a1  b2, b3, b4  c1, c2, c3  d1, d2, d3  NA          NA
a2  b1, b2, b3  c2, c5, c6  d1, d2, d3  e2, e3, e4  NA
a5  b5, b6, b7  c1, c2, c3  d1, d2, d3  NA          NA
a6  b1, b2, b3  c1, c4, c5  d1, d2, d3  e1, e2, e3  f1, f2, f3

考虑到我有一个包含 100k+ 行的 data.table,什么是最快的方法?

【问题讨论】:

  • 您自己有没有尝试过但速度太慢的想法?

标签: r string data.table str-replace


【解决方案1】:
DT <- DT[, tstrsplit(string, "; [a-z]:")]
# If data is in alphabetical order
setnames(DT, letters[1:6])
# Otherwise smth like this: 
setnames(
  DT,
  DT[, sapply(.SD, function(x) stringr::str_extract(x[!is.na(x)], "[a-z]")[[1]])]
)
    a           b           c           d           e           f
1: a1  b1, b2, b3  c1, c2, c3        <NA>        <NA>        <NA>
2: a1  b2, b3, b4  c1, c2, c3  d1, d2, d3        <NA>        <NA>
3: a2  b1, b2, b3  c2, c5, c6  d1, d2, d3  e2, e3, e4        <NA>
4: a5  b5, b6, b7  c1, c2, c3  d1, d2, d3        <NA>        <NA>
5: a6  b1, b2, b3  c1, c4, c5  d1, d2, d3  e1, e2, e3  f1, f2, f3

可重现的数据:

DT <- fread(
  "string
  a1; b: b1, b2, b3; c: c1, c2, c3
  a1; b: b2, b3, b4; c: c1, c2, c3; d: d1, d2, d3
  a2; b: b1, b2, b3; c: c2, c5, c6; d: d1, d2, d3; e: e2, e3, e4 
  a5; b: b5, b6, b7; c: c1, c2, c3; d: d1, d2, d3
  a6; b: b1, b2, b3; c: c1, c4, c5; d: d1, d2, d3; e: e1, e2, e3; f: f1, f2, f3",
  sep = "\n"
)

【讨论】:

    【解决方案2】:

    使用dplyrtidyr 的一种方式

    library(dplyr)
    library(tidyr)
    
    df %>%
      mutate(row = row_number()) %>%
      separate_rows(string, sep = ";") %>%
      separate(string, into = c('column', 'value'), sep = ":\\s+", fill = 'left') %>%
      mutate(column = replace_na(column, 'a')) %>%
      pivot_wider(names_from = column, values_from = value) %>%
      select(-row)
    
    
    #  a     ` b`       ` c`       ` d`       ` e`       ` f`      
    #  <chr> <chr>      <chr>      <chr>      <chr>      <chr>     
    #1 a1    b1, b2, b3 c1, c2, c3 NA         NA         NA        
    #2 a1    b2, b3, b4 c1, c2, c3 d1, d2, d3 NA         NA        
    #3 a2    b1, b2, b3 c2, c5, c6 d1, d2, d3 e2, e3, e4 NA        
    #4 a5    b5, b6, b7 c1, c2, c3 d1, d2, d3 NA         NA        
    #5 a6    b1, b2, b3 c1, c4, c5 d1, d2, d3 e1, e2, e3 f1, f2, f3
    

    数据

    df <- structure(list(string = c("a1; b: b1, b2, b3; c: c1, c2, c3", 
    "a1; b: b2, b3, b4; c: c1, c2, c3; d: d1, d2, d3", "a2; b: b1, b2, b3; c: c2, c5, c6; d: d1, d2, d3; e: e2, e3, e4", 
    "a5; b: b5, b6, b7; c: c1, c2, c3; d: d1, d2, d3", "a6; b: b1, b2, b3; c: c1, c4, c5; d: d1, d2, d3; e: e1, e2, e3; f: f1, f2, f3"
    )), class = "data.frame", row.names = c(NA, -5L))
    

    【讨论】:

      【解决方案3】:

      我们可以从splitstackshape使用cSplit

      library(splitstackshape)
      out <- cSplit(DT, "string", sep=";\\s*", fixed = FALSE)
      names(out) <- letters[seq_along(out)]
      out
      #    a               b               c               d               e               f
      #1: a1 s*b: b1, b2, b3 s*c: c1, c2, c3            <NA>            <NA>            <NA>
      #2: a1 s*b: b2, b3, b4 s*c: c1, c2, c3 s*d: d1, d2, d3            <NA>            <NA>
      #3: a2 s*b: b1, b2, b3 s*c: c2, c5, c6 s*d: d1, d2, d3 s*e: e2, e3, e4            <NA>
      #4: a5 s*b: b5, b6, b7 s*c: c1, c2, c3 s*d: d1, d2, d3            <NA>            <NA>
      #5: a6 s*b: b1, b2, b3 s*c: c1, c4, c5 s*d: d1, d2, d3 s*e: e1, e2, e3 s*f: f1, f2, f3
      

      数据

      DT <- structure(list(string = c("a1; b: b1, b2, b3; c: c1, c2, c3", 
      "a1; b: b2, b3, b4; c: c1, c2, c3; d: d1, d2, d3", "a2; b: b1, b2, b3; c: c2, c5, c6; d: d1, d2, d3; e: e2, e3, e4", 
      "a5; b: b5, b6, b7; c: c1, c2, c3; d: d1, d2, d3", "a6; b: b1, b2, b3; c: c1, c4, c5; d: d1, d2, d3; e: e1, e2, e3; f: f1, f2, f3"
      )), row.names = c(NA, -5L), class = "data.frame")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-12
        • 2023-03-20
        • 2016-12-29
        • 1970-01-01
        • 2014-08-07
        • 2021-03-26
        • 2021-02-28
        • 2021-12-07
        相关资源
        最近更新 更多