如何规范化 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}))
我有一个 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}))