R中多个列中data.table中的单独字符串列

问题描述 投票:0回答:3

想象一下我有一个带有以下字符串列的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
3个回答
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"
)

1
投票

使用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))

1
投票

我们可以使用cSplit中的splitstackshape

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")
© www.soinside.com 2019 - 2024. All rights reserved.