2015-04-14 5 views
17

Я пытаюсь применить несколько функций к нескольким столбцам data.table. Пример:data.table в R - применить несколько функций к нескольким столбцам

DT <- data.table("a"=1:5, 
       "b"=2:6, 
       "c"=3:7) 

Скажем, я хочу, чтобы получить среднее и медиану колонн a и b. Это работает:

stats <- DT[,.(mean_a=mean(a), 
       median_a=median(a), 
       mean_b=mean(b), 
       median_b=median(b))] 

Но это слишком повторы. Есть ли хороший способ добиться аналогичного результата, используя .SDcols и lapply?

+1

Почему бы не поставить функции в пользовательскую функцию и называем это? – A5C1D2H2I1M1N2O1R2T1

+3

Или, может быть, посмотрите версию разработки «data.table», где 'dcast' может обрабатывать сразу несколько столбчатых агрегатов. – A5C1D2H2I1M1N2O1R2T1

+2

Это может быть проще с помощью 'dplyr'' summaryise_each (DT, funs (mean, median), 1: 2) ' – akrun

ответ

18

я обычно это сделать:

my.summary = function(x) list(mean = mean(x), median = median(x)) 

DT[, unlist(lapply(.SD, my.summary)), .SDcols = c('a', 'b')] 
#a.mean a.median b.mean b.median 
#  3  3  4  4 
+1

У меня была аналогичная идея, но я думал, что OP хочет получить вывод data.table вместо вектора 'DT [, as.list (unlist (lapply (.SD, my.summary))) .SDcols = c ('a' , 'b')] ' – akrun

+5

Возможно, вы также, возможно, упростите функцию' my.summary = function (x) c (mean = mean (x), median = median (x)); DT [, sapply (.SD, my.summary), .SDcols = a: b] ' –

+2

Но это кажется ужасно медленным, если я добавляю группу по категориям ' DT [, as.list (unlist (lapply (. SD, my.summary))), by = category, .SDcols = c ('a', 'b')] ' Это занимает гораздо больше времени, чем выполнение каждого сводного описания индивидуально, а затем присоединение. Любой более быстрый способ сделать это? У меня около 1,5 миллионов групп в колонке категории @akrun – sriramn

7

Это немного неуклюжим, но делает работу с data.table:

funcs = c('median', 'mean', 'sum') 

m = DT[, lapply(.SD, function(u){ 
     sapply(funcs, function(f) do.call(f,list(u))) 
    })][, t(.SD)] 
colnames(m) = funcs 

# median mean sum 
#a  3 3 15 
#b  4 4 20 
#c  5 5 25 
+0

Ницца, спасибо. – paljenczy

+0

Добро пожаловать! –

+1

Добавление новой зависимости только для одного вызова 't()', кажется, немного накладные расходы, почему бы не использовать цепочку? 'm = DT [...] [, t (.SD)]'. Я думаю, что это также более читаемо. – jangorecki