2016-06-10 12 views
6

Was ist der idiomatische data.table-Ansatz, um eine data.table mit separaten Spalten für Elemente eines Vektors zu erzeugen, die von einer Funktion zurückgegeben werden, berechnet nach Gruppe?transponierter Vektor nach Gruppe in data.table

Betrachten Sie die data.table:

library(data.table) 
data(iris) 
setDT(iris) 

Wenn die Funktion range() ist, ich die Ausgabe auf ähnliche wollen würde:

iris[, .(min_petal_width = min(Petal.Width), 
     max_petal_width = max(Petal.Width) 
     ), keyby = Species] # produces desired output 

aber die range() Funktion.

kann ich dcast verwenden, aber es ist hässlich:

dcast(
    iris[, .(petal_width = range(Petal.Width), 
      value = c("min_petal_width", "max_petal_width")), 
     keyby = Species], 
    Species ~ value, value.var = "petal_width") 

Ich hoffe, es ist ein einfacher Ausdruck, entlang der Linien von:

iris[, (c("min_petal_width","max_petal_width")) = range(Petal.Width), 
     keyby = Species] # doesn't work 

Antwort

5

Ihr Ansatz sehr nahe war. Denken Sie daran, dass Sie der Datei data.table eine Liste hinzufügen müssen, die sie gerne akzeptiert. Daher können Sie verwenden:

iris[, c("min_petal_width","max_petal_width") := as.list(range(Petal.Width)), 
    by = Species] 

ich die Frage falsch verstanden .. Da Sie das Ergebnis statt Hinzufügen neuer Spalten aggregieren möchten, können Sie

cols <- c("min_petal_width", "max_petal_width") 
iris[, setNames(as.list(range(Petal.Width)), cols), keyby = Species] 

Aber ich bin sicher, es gibt ein verwenden einige andere data.table Ansätze auch.

+2

Dies stellt keine neue data.table zurück, aber es ändert Iris data.table an Ort und Stelle zwei Spalten, um es – digEmAll

+0

@digEmAll hinzufügen, oh, du ist natürlich recht. –

6

Sie können auch tun:

dt[, lapply(list(min=min, max=max), function(f) f(Petal.Width)), by=Species] 
#  Species min max 
# 1:  setosa 0.1 0.6 
# 2: versicolor 1.0 1.8 
# 3: virginica 1.4 2.5 
2

Wenn Lesbarkeit und Prägnanz zu Ihnen wirklich wichtig ist, würde ich eine benutzerdefinierte Funktion oder Binäroperators definieren, die Sie dann einfach in Ihrem data.table Teilmenge Ausdruck verwenden, z.B. :

# custom function 
.nm <- function(v,vnames){ 
    `names<-`(as.list(v),vnames) 
} 
# custom binary operator 
`%=%` <- function(vnames,v){ 
    `names<-`(as.list(v),vnames) 
} 

# using custom function 
iris[, .nm(range(Petal.Width),c("min_petal_width", "max_petal_width")), keyby = Species] 

# using custom binary operator 
iris[, c("min_petal_width", "max_petal_width") %=% range(Petal.Width), keyby = Species] 
Verwandte Themen