2013-04-17 6 views
5

dato un oggetto data.table Vorrei ridurre i valori di alcune colonne raggruppate in un singolo oggetto e inserire gli oggetti risultanti in una nuova colonna.Riduci i valori delle colonne data.table durante il raggruppamento

dt <- data.table(
      c('A|A', 'B|A', 'A|A', 'B|A', 'A|B'), 
      c(0, 0, 1, 1, 0), 
      c(22.7, 1.2, 0.3, 0.4, 0.0) 
) 
setnames(dt, names(dt), c('GROUPING', 'NAME', 'VALUE')) 
dt 
# GROUPING NAME VALUE 
# 1:  A|A 0 22.7 
# 2:  B|A 0 1.2 
# 3:  A|A 1 0.3 
# 4:  B|A 1 0.4 
# 5:  A|B 0 0.0 

Penso che per fare questo è prima necessario specificare la colonna per la quale si desidera raggruppare, quindi dovrebbe iniziare con qualcosa di simile dt[, OBJECTS := <expr>, by = GROUPING].

Purtroppo, non so l'espressione <expr> da usare in modo che il risultato è il seguente:

# GROUPING OBJECTS 
# 1:  A|A <vector> 
# 2:  B|A <vector> 
# 3:  A|B <vector> 

Ogni <vector> deve contenere i valori delle altre colonne. Per esempio il primo <vector> deve essere un vettore di nome equivalente a:

eg <- c(22.7, 0.3) 
names(eg) <- c('0', '1') 
# 0 1 
# 22.7 0.3 
+0

Stai cercando di rimodellare i dati.table in formato wide? – mnel

+0

il tuo 'expr' dovrebbe apparire come' lista (lista (...)) ' –

+0

Ma perché? Non pensi che sia difficile lavorare con questo? Perché non rimodellarlo e avere colonne con valori corrispondenti a '0' e' 1'? – Arun

risposta

3

ho pensare che questo è quello che stai cercando:

dt1 <- dt[, list(list(setNames(VALUE, NAME))), by = GROUPING] 
dt1 
# GROUPING  V1 
# 1:  A|A 22.7,0.3 
# 2:  B|A 1.2,0.4 
# 3:  A|B  0 
str(dt1) 
# Classes ‘data.table’ and 'data.frame': 3 obs. of 2 variables: 
# $ GROUPING: chr "A|A" "B|A" "A|B" 
# $ V1  :List of 3 
# ..$ : Named num 22.7 0.3 
# .. ..- attr(*, "names")= chr "0" "1" 
# ..$ : Named num 1.2 0.4 
# .. ..- attr(*, "names")= chr "0" "1" 
# ..$ : Named num 0 
# .. ..- attr(*, "names")= chr "0" 
# - attr(*, ".internal.selfref")=<externalptr> 
dt1$V1 
# [[1]] 
# 0 1 
# 22.7 0.3 
# 
# [[2]] 
# 0 1 
# 1.2 0.4 
# 
# [[3]] 
# 0 
# 0 

Come sottolinea @Arun nei commenti, il "data.table "alternativa a setNames in questo caso è setattr(VALUE, 'names', NAME), facendo un'altra soluzione:

dt1 <- dt[, list(list(setattr(VALUE, 'names', NAME))), by = GROUPING] 
+0

Penso che dovresti usare 'setnames', non' setNames'. – Arun

+0

@Arun, puoi mostrare come? Non ci sono vecchi nomi, quindi non sono sicuro di come procedere, quindi ho usato 'setNames' dalla base R. – A5C1D2H2I1M1N2O1R2T1

+1

Ananda, oh capisco. In tal caso, è bello usare 'setattr (VALUE, 'nomi', NOME)' – Arun

5

Lavorare all'interno di j: Se si desidera avere i valori di una colonna di essere un vettore, è necessario avvolgere l'output in list(.).

j per sé richiede una chiamata a list, così il vostro espressione finale assomiglierà ad un nidificato list, ad esempio:

dt[, list(allNames=list(NAME), allValues=list(VALUE)), by=GROUPING] 

# GROUPING allNames allValues 
# 1:  A|A  0,1 22.7,0.3 
# 2:  B|A  0,1 1.2,0.4 
# 3:  A|B  0   0 

Come @Mnel sottolinea, in modo equivalente:

dt[, lapply(.SD, list), by=GROUPING] 

Se lo vuoi in forma estesa, quindi la struttura del tuo <expr> sarà:
list(c( list(), list(), ..., list() )) ad es .:

dt[, list(c(list(NAME), list(VALUE))), by=GROUPING] 

# GROUPING  V1 
# 1:  A|A  0,1 
# 2:  A|A 22.7,0.3 
# 3:  B|A  0,1 
# 4:  B|A 1.2,0.4 
# 5:  A|B  0 
# 6:  A|B  0 

o equivalentemente:

dt[, list(lapply(.SD, c)), by=GROUPING]