2012-07-27 22 views
88

Jaki jest najlepszy sposób przypisania do wielu kolumn przy użyciu data.table? Na przykład:Przypisywanie wielu kolumn za pomocą: = w data.table, według grupy

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

chciałbym zrobić coś takiego (oczywiście ta składnia jest błędna):

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

i rozszerzenia, które mogą Mam wiele kolumn z nazwami w zmiennej (słownie column_names) i chciałbym zrobić:

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

Jaki jest prawidłowy sposób zrobić coś takiego?

+1

To wygląda jak został on odpowiedział: http://stackoverflow.com/questions/11308754/add-multiple-columns-to-r-data- table-in-one-function-call – Alex

+0

Alex, Ta odpowiedź jest blisko, ale nie wydaje się działać w połączeniu z 'by', ponieważ @Christoph_J ma rację. Link do Twojego pytania został dodany do [FR # 2120] (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2120&group_id=240&atid=978) "Upuść wymaganie z = FALSE dla LHS z: = ", więc nie zapomni się o ponownym odwiedzeniu. –

Odpowiedz

106

Działa to teraz w wersji 1.8.3 na R-Forge. Dzięki za podkreślenie tego!

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

Dziękuję za tę odpowiedź i przykłady. W jaki sposób zmodyfikować poniższy wiersz, aby uzyskać dwie kolumny dla każdego obiektu objectName z dim output, a nie jedną kolumnę z dwoma wierszami? 'data.table (objectName = ls()) [, c (" rows "," cols "): = dim (get (objectName)), by = objectName]' (Używam 'data.table' 1.8. 11) – dnlbrky

+0

@dnlbrky 'dim' zwraca wektor, więc konwertowanie go do typu' list' powinno go obrócić; na przykład '[, c (" rows "," cols "): = as.list (dim (get (objectName))), by = objectNa me]'. Problem polega na tym, że 'as.list' ma narzut na telefon i kopiuje mały wektor. Jeśli efektywność jest problemem, ponieważ liczba grup wzrasta, daj nam znać. –

+0

Dzięki @Matt_Dowle. Próbowałem 'list', ale nie' as.list'. Prędkość nie jest problemem. Po prostu chciałem szybko znaleźć obiekty w środowisku, które miały określoną liczbę kolumn lub wierszy. To nie jest temat, ale ... co myślisz o dodaniu NCOL do 'tables()'? – dnlbrky

Powiązane problemy