Używanie dynamicznych nazw kolumn w ' data.tabela"
Chcę obliczyć średnią każdej z kilku kolumn w danych.tabela, pogrupowana według innej kolumny. Moje pytanie jest podobne do dwóch innych pytań dotyczących SO (Jeden i dwa), ale nie mogłem zastosować ich do mojego problemu.
Oto przykład:
library(data.table)
dtb <- fread(input = "condition,var1,var2,var3
one,100,1000,10000
one,101,1001,10001
one,102,1002,10002
two,103,1003,10003
two,104,1004,10004
two,105,1005,10005
three,106,1006,10006
three,107,1007,10007
three,108,1008,10008
four,109,1009,10009
four,110,1010,10010")
dtb
# condition var1 var2 var3
# 1: one 100 1000 10000
# 2: one 101 1001 10001
# 3: one 102 1002 10002
# 4: two 103 1003 10003
# 5: two 104 1004 10004
# 6: two 105 1005 10005
# 7: three 106 1006 10006
# 8: three 107 1007 10007
# 9: three 108 1008 10008
# 10: four 109 1009 10009
# 11: four 110 1010 10010
Obliczenie każdej pojedynczej średniej jest łatwe; np. dla "var1": dtb[ , mean(var1), by = condition]
. Ale to szybko staje się kłopotliwe, jeśli istnieje wiele zmiennych i trzeba napisać wszystkie z nich. Tak więc, dtb[, list(mean(var1), mean(var2), mean(var3)), by = condition]
jest niepożądane. Potrzebuję kolumny. nazwy żeby były dynamiczne i chciałbym skończyć z czymś takim:
condition var1 var2 var3
1: one 101.0 1001.0 10001.0
2: two 104.0 1004.0 10004.0
3: three 107.0 1007.0 10007.0
4: four 109.5 1009.5 10009.5
1 answers
Powinieneś użyć .SDcols
(zwłaszcza jeśli masz zbyt wiele kolumn i wymagasz wykonania konkretnej operacji tylko na podzbiorze kolumn (poza zmienną grupującą kolumny).
dtb[, lapply(.SD, mean), by=condition, .SDcols=2:4]
# condition var1 var2 var3
# 1: one 101.0 1001.0 10001.0
# 2: two 104.0 1004.0 10004.0
# 3: three 107.0 1007.0 10007.0
# 4: four 109.5 1009.5 10009.5
Możesz również pobrać wszystkie nazwy kolumn, które chcesz wziąć jako pierwsze w zmiennej, a następnie przekazać je do .SDcols
w następujący sposób:
keys <- setdiff(names(dtb), "condition")
# keys = var1, var2, var3
dtb[, lapply(.SD, mean), by=condition, .SDcols=keys]
Edit: jak słusznie zauważył Mateusz Dowle, skoro trzeba obliczyć średnią na każdej innej kolumnie po pogrupowaniu przez condition
, można po prostu zrobić:
dtb[, lapply(.SD, mean), by=condition]
David ' s edit: (który został odrzucony): Read more about .SD
from this post. Uważam, że jest to istotne. Dzięki @ David.
Edit 2: Załóżmy, że masz data.table
ze 1000 wierszami i 301 kolumnami (jedna kolumna do grupowania i 300 kolumn numerycznych):
require(data.table)
set.seed(45)
dt <- data.table(grp = sample(letters[1:15], 1000, replace=T))
m <- matrix(rnorm(300*1000), ncol=300)
dt <- cbind(dt, m)
setkey(dt, "grp")
I chciałeś znaleźć średnią kolumn, powiedzmy, 251: 300 sam,
-
Możesz obliczyć średnią wszystkich kolumny, a następnie podgrupuj te kolumny (co nie jest zbyt wydajne, jak obliczysz na całych danych).
dt.out <- dt[, lapply(.SD, mean), by=grp] dim(dt.out) # 15 * 301, not efficient.
-
Możesz przefiltrować
data.table
najpierw do tych kolumn, a następnie obliczyć średnią (co ponownie niekoniecznie jest najlepszym rozwiązaniem, ponieważ musisz utworzyć dodatkowy podzbiór danych.tabela za każdym razem, gdy chcesz operacji na określonych kolumnach.dt.sub <- dt[, c(1, 251:300), with=FALSE] setkey(dt.sub, "grp") dt.out <- dt.sub[, lapply(.SD, mean), by=grp]
-
Możesz określić każdą z kolumn jeden po drugim, jak zwykle (ale jest to pożądane dla mniejsze dane.tabele)
# if you just need one or few columns dt.out <- dt[, list(m.v251 = mean(V251)), by = grp]
Więc jakie jest najlepsze rozwiązanie? Odpowiedź brzmi .SDcols .
Zgodnie z dokumentacją, dla danych.tabela x, .SDcols określa kolumny, które są zawarte w . SD .
To w zasadzie domyślnie filtruje kolumny, które zostaną przekazane do. SD zamiast tworzyć podzbiór (jak to zrobiliśmy wcześniej), tylko jest bardzo wydajne i szybkie!
Jak możemy to zrobić?-
Określając numery kolumn:
dt.out <- dt[, lapply(.SD, mean), by=grp, .SDcols = 251:300] dim(dt.out) # 15 * 51 (what we expect)
-
Lub alternatywnie przez podanie ID kolumny:
ids <- paste0("V", 251:300) # get column ids dt.out <- dt[, lapply(.SD, mean), by=grp, .SDcols = ids] dim(dt.out) # 15 * 51 (what we expect)
Przyjmuje zarówno nazwy kolumn, jak i liczby jako argumenty. W obu tych przypadkach .SD będzie dostarczane tylko z tymi kolumnami, które określiliśmy.
Mam nadzieję, że to pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:11