我想转换:
library(data.table)
n <- 12
DT <- data.table(
level1 = rep(paste0("Manu", 1:2), each = n / 2),
level2 = rep(paste0("Dept", 1:4), each = n / 4),
level3 = rep(paste0("Store", 1:n))
)
> DT
level1 level2 level3
1: Manu1 Dept1 Store1
2: Manu1 Dept1 Store2
3: Manu1 Dept1 Store3
4: Manu1 Dept2 Store4
5: Manu1 Dept2 Store5
6: Manu1 Dept2 Store6
7: Manu2 Dept3 Store7
8: Manu2 Dept3 Store8
9: Manu2 Dept3 Store9
10: Manu2 Dept4 Store10
11: Manu2 Dept4 Store11
12: Manu2 Dept4 Store12
对此:
goal <- list(
Manu1 = list(
Dept1 = paste0("Store", 1:(n / 4)),
Dept2 = paste0("Store", (n/4 + 1):(n / 2))
),
Manu2 = list(
Dept3 = paste0("Store", (n/2 + 1):(3 * n / 4)),
Dept4 = paste0("Store", (3 * n / 4 + 1):n)
)
)
> goal
$Manu1
$Manu1$Dept1
[1] "Store1" "Store2" "Store3"
$Manu1$Dept2
[1] "Store4" "Store5" "Store6"
$Manu2
$Manu2$Dept3
[1] "Store7" "Store8" "Store9"
$Manu2$Dept4
[1] "Store10" "Store11" "Store12"
data.table
这样做的方法是什么?
答案 0 :(得分:4)
使用assign
和朋友而不是全局<<-
可以更严格地制定环境,但这是一种快速而肮脏的方式:
l = list()
DT[, {l[[level1]][[level2]] <<- c(level3); NULL}, by = .(level1, level2)]
l
#$Manu1
#$Manu1$Dept1
#[1] "Store1" "Store2" "Store3"
#
#$Manu1$Dept2
#[1] "Store4" "Store5" "Store6"
#
#
#$Manu2
#$Manu2$Dept3
#[1] "Store7" "Store8" "Store9"
#
#$Manu2$Dept4
#[1] "Store10" "Store11" "Store12"
答案 1 :(得分:4)
借用@ eddi的评论(需要将data.table
更新为1.9.8 +):
s = split(DT, by = c('level1', 'level2'), keep.by = FALSE, flatten = FALSE)
rapply(relist(DT[['level3']], s), unname, how="replace")
$Manu1
$Manu1$Dept1
[1] "Store1" "Store2" "Store3"
$Manu1$Dept2
[1] "Store4" "Store5" "Store6"
$Manu2
$Manu2$Dept3
[1] "Store7" "Store8" "Store9"
$Manu2$Dept4
[1] "Store10" "Store11" "Store12"
计算上,这看起来非常浪费(迭代树结构三次),但至少它应该延伸到更深的嵌套而不是两个级别(感谢1.9.8 +中的split.data.table
)。
答案 2 :(得分:3)
您可以使用dlply
包中的plyr
函数执行此操作:
library(plyr)
res <- dlply(DT, .(level1), function(dt) {
dlply(dt, .(level2), function(dt) {return (unique(dt$level3))})
})