2012-07-27 16 views
88

Was ist der beste Weg, um mehrere Spalten mit data.table zuzuweisen? Zum Beispiel:Mehrere Spalten zuweisen mit: = in data.table, nach Gruppe

f <- function(x) {c("hi", "hello")} 
x <- data.table(id = 1:10) 

Ich möchte so etwas wie dies tun (natürlich diese Syntax ist falsch):

x[ , (col1, col2) := f(), by = "id] 

und zu erweitern, dass ich viele Spalten mit Namen in einer Variablen haben (sagen column_names) und ich würde gerne tun:

x[ , col_names := another_f(), by = "id", with = FALSE] 

Was ist der richtige Weg, so etwas zu tun?

+1

Das sieht aus wie es beantwortet wurde: http://stackoverflow.com/questions/11308754/add-multiple-columns-to-r-data- table-in-one-function-call – Alex

+0

Alex, Diese Antwort ist nahe, aber es scheint nicht in Kombination mit 'by' zu funktionieren, wie @Christoph_J zu sagen hat. Link zu Ihrer Frage, die zu [FR # 2120] hinzugefügt wurde (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2120&group_id=240&atid=978) "Drop braucht mit = FALSE für LHS von: = ", damit es nicht wieder vergessen wird, es zu wiederholen. –

Antwort

106

Dies funktioniert jetzt in v1.8.3 auf R-Forge. Danke für die Hervorhebung!

x <- data.table(a = 1:3, b = 1:6) 
f <- function(x) {list("hi", "hello")} 
x[ , c("col1", "col2") := f(), by = a][] 
# a b col1 col2 
# 1: 1 1 hi hello 
# 2: 2 2 hi hello 
# 3: 3 3 hi hello 
# 4: 1 4 hi hello 
# 5: 2 5 hi hello 
# 6: 3 6 hi hello 

x[ , c("mean", "sum") := list(mean(b), sum(b)), by = a][] 
# a b col1 col2 mean sum 
# 1: 1 1 hi hello 2.5 5 
# 2: 2 2 hi hello 3.5 7 
# 3: 3 3 hi hello 4.5 9 
# 4: 1 4 hi hello 2.5 5 
# 5: 2 5 hi hello 3.5 7 
# 6: 3 6 hi hello 4.5 9 

mynames = c("Name1", "Longer%") 
x[ , (mynames) := list(mean(b) * 4, sum(b) * 3), by = a] 
#  a b col1 col2 mean sum Name1 Longer% 
# 1: 1 1 hi hello 2.5 5 10  15 
# 2: 2 2 hi hello 3.5 7 14  21 
# 3: 3 3 hi hello 4.5 9 18  27 
# 4: 1 4 hi hello 2.5 5 10  15 
# 5: 2 5 hi hello 3.5 7 14  21 
# 6: 3 6 hi hello 4.5 9 18  27 


x[ , mynames := list(mean(b) * 4, sum(b) * 3), by = a, with = FALSE][] # same 
# a b col1 col2 mean sum Name1 Longer% 
# 1: 1 1 hi hello 2.5 5 10  15 
# 2: 2 2 hi hello 3.5 7 14  21 
# 3: 3 3 hi hello 4.5 9 18  27 
# 4: 1 4 hi hello 2.5 5 10  15 
# 5: 2 5 hi hello 3.5 7 14  21 
# 6: 3 6 hi hello 4.5 9 18  27 

x[ , get("mynames") := list(mean(b) * 4, sum(b) * 3), by = a][] # same 
# a b col1 col2 mean sum Name1 Longer% 
# 1: 1 1 hi hello 2.5 5 10  15 
# 2: 2 2 hi hello 3.5 7 14  21 
# 3: 3 3 hi hello 4.5 9 18  27 
# 4: 1 4 hi hello 2.5 5 10  15 
# 5: 2 5 hi hello 3.5 7 14  21 
# 6: 3 6 hi hello 4.5 9 18  27 

x[ , eval(mynames) := list(mean(b) * 4, sum(b) * 3), by = a][] # same 
# a b col1 col2 mean sum Name1 Longer% 
# 1: 1 1 hi hello 2.5 5 10  15 
# 2: 2 2 hi hello 3.5 7 14  21 
# 3: 3 3 hi hello 4.5 9 18  27 
# 4: 1 4 hi hello 2.5 5 10  15 
# 5: 2 5 hi hello 3.5 7 14  21 
# 6: 3 6 hi hello 4.5 9 18  27 
+0

Danke für diese Antwort und die Beispiele. Wie sollte ich die folgende Zeile ändern, um zwei Spalten für jeden Objektnamen aus der Dim-Ausgabe zu erhalten, anstatt eine Spalte mit zwei Zeilen? 'data.table (objectName = ls()) [, c (" Zeilen "," Spalten "): = dim (get (Objektname)), by = Objektname]' (Ich benutze 'data.table' 1.8. 11) – dnlbrky

+0

@dnlbrky 'dim' gibt einen Vektor zurück, also sollte der Name in' list' umgewandelt werden; z.B. '[, c (" rows "," cols "): = as.list (dim (get (objectName))), durch = objectNa me]'. Problem ist, dass 'as.list' einen Anruf-Overhead hat und auch den kleinen Vektor kopiert. Wenn die Effizienz ein Problem ist, wenn die Anzahl der Gruppen steigt, lassen Sie es uns bitte wissen. –

+0

Danke @Matt_Dowle. Ich hatte versucht "Liste", aber nicht "as.list". Geschwindigkeit ist kein Problem. Wollte nur einen schnellen Weg, um Objekte in der Umgebung zu finden, die eine bestimmte Anzahl von Spalten oder Zeilen hatten. Das ist nicht im Thema, aber ... Was denkst du über das Hinzufügen von NCOL zu 'tables()'? – dnlbrky

Verwandte Themen