如何规范化 R 中数据 table 中的多值列

How to normalize multiple-values-column in a data table in R

我有一个 data.table 如下:

order   products    value
1000    A|B 10
2000    B|C 20
3000    A|C 30
4000    B|C|D   5
5000    C|D 15

我需要打破列产品和 transform/normalize 才能像这样使用:

order   prod.seq    prod.name   value
1000    1   A   10
1000    2   B   10
2000    1   B   20
2000    2   C   20
3000    1   A   30
3000    2   C   30
4000    1   B   5
4000    2   C   5
4000    3   D   5
5000    1   C   15
5000    2   D   15

我想我可以使用自定义 FOR/LOOP 来做到这一点,但我想知道一种更高级的方法来使用 apply,ddply 方法来做到这一点。有什么建议吗?

首先,转换为 character/string:

DT[,products:=as.character(products)]

然后就可以拆分字符串了:

DT[,{
  x = strsplit(products,"\|")[[1]]
  list( prod.seq = seq_along(x), prod_name = x )
}, by=.(order,value)]

这给出了

    order value prod.seq prod_name
 1:  1000    10        1         A
 2:  1000    10        2         B
 3:  2000    20        1         B
 4:  2000    20        2         C
 5:  3000    30        1         A
 6:  3000    30        2         C
 7:  4000     5        1         B
 8:  4000     5        2         C
 9:  4000     5        3         D
10:  5000    15        1         C
11:  5000    15        2         D

这是另一个选项

library(splitstackshape)
out = cSplit(dat, "products", "|", direction = "long")
out[, prod.seq := seq_len(.N), by = value]

#> out
#    order products value prod.seq
# 1:  1000        A    10        1
# 2:  1000        B    10        2
# 3:  2000        B    20        1
# 4:  2000        C    20        2
# 5:  3000        A    30        1
# 6:  3000        C    30        2
# 7:  4000        B     5        1
# 8:  4000        C     5        2
# 9:  4000        D     5        3
#10:  5000        C    15        1
#11:  5000        D    15        2

cSplit 步骤之后,使用 ddply

library(plyr)
ddply(out, .(value), mutate, prod.seq = seq_len(length(order)))

使用dplyr

library(dplyr)
out %>% group_by(value) %>% mutate(prod.seq = row_number(order))

使用lapply

rbindlist(lapply(split(out, out$value), 
          function(x){x$prod.seq = seq_len(length(x$order));x}))