2013-04-17 12 views
5

gegeben ein data.table Objekt Ich würde die Werte einiger gruppierter Spalten in ein einzelnes Objekt reduzieren und die resultierenden Objekte in eine neue Spalte einfügen.Collapse data.table Spaltenwerte während Gruppierung

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 

denke ich, dass dies zu tun, zuerst notwendig ist, um die Spalte, für die Sie gruppieren möchten angeben, also sollte ich mit so etwas wie dt[, OBJECTS := <expr>, by = GROUPING] starten.

Leider weiß ich nicht den Ausdruck <expr> so zu verwenden, dass das Ergebnis wie folgt:

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

Jeder <vector> die Werte der anderen Spalten enthalten muss.

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

Möchten Sie Ihre data.table in ein Wide Format umformen? – mnel

+0

Ihr 'Ausdruck' sollte ungefähr so ​​aussehen wie 'Liste (Liste (...))' –

+0

Aber warum? Denkst du nicht, dass es schwierig ist, damit zu arbeiten? Warum nicht umformen und Spalten mit Werten haben, die "0" und "1" entsprechen? – Arun

Antwort

3

ich denken, dass dies ist, was Sie suchen:

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 

Wie @Arun in den Kommentaren weist darauf hin, die „data.table "Alternative zu setNames in diesem Fall ist setattr(VALUE, 'names', NAME), eine andere Lösung machend:

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

Ich denke, du solltest 'setnames' verwenden, nicht' setNames'. – Arun

+0

@Arun, können Sie zeigen, wie? Es gibt keine alten Namen, also bin ich mir nicht sicher, wie ich das machen soll, also habe ich 'setNames' von Base R verwendet. – A5C1D2H2I1M1N2O1R2T1

+1

Ananda, oh, ich verstehe. In diesem Fall ist es schön, 'setattr (VALUE, 'names', NAME) zu verwenden' – Arun

5

Arbeiten innerhalb von j: z.B die erste <vector> haben einen benannten Vektor äquivalent sein, wenn Sie die Werte einer Spalte sein, einen Vektor haben wollen, müssen Sie die Ausgabe in list(.) wickeln.

j selbst erfordert einen Aufruf list, so dass Ihre endgültige Ausdruck wird eine verschachtelte list, zum Beispiel ähneln:

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 

Wie @Mnel weist darauf hin, äquivalent:

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

Wenn Sie es wünschen in der langen Form, dann die Struktur von Ihrem <expr> wird sein:
list(c( list(), list(), ..., list() )) zB:

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 

oder äquivalent:

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