2016-05-19 12 views
7

chciałbym skonwertować:Tabela danych do zagnieżdżonej listy

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 

do tego:

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" 

Jaki jest sposób data.table to zrobić?

+2

'split (DT, by = c ('level1', 'level2'), keep.by = FALSE, spłaszczyć = FALSE)' zajmie ci większość drogi – eddi

+1

@eddi - czy to stosunkowo nowy dodatek do data.table - Wydaje mi się, że nie mam go tutaj. – thelatemail

+0

@ theailemail tak, jest w wersji devel (wiele ciekawych funkcji zostało dodanych ostatnio, więc zacząłem używać devel i wciąż zapominam, że nie działam 1.9.6) – eddi

Odpowiedz

4

Pożyczanie od użytkownika @ Eddi komentarzu (która wymaga aktualizacji data.table do 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" 

To wygląda całkiem nieefektywnie (trzykrotne powtarzanie struktury drzewa), ale przynajmniej powinno rozciągać się na głębsze zagnieżdżanie niż dwa poziomy (dzięki split.data.table w wersji 1.9.8+).

4

środowiska mogą być surowsze użyciu assign i przyjaciół zamiast globalnego <<-, ale tutaj jest to szybki i brudny sposób to zrobić:

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" 
3

Można to zrobić z dlply funkcji z plyr opakowaniu:

library(plyr) 
res <- dlply(DT, .(level1), function(dt) { 
    dlply(dt, .(level2), function(dt) {return (unique(dt$level3))}) 
})