2016-08-10 1 views
2

Вот простая проблема, которую я пытаюсь решить: у меня есть таблица данных, как следующая таблица, и я пытаюсь использовать функцию dcast.data.table для вычисления числа продвижения для каждой группы, но я заинтересован, чтобы вычислить median сортов в каждой группе:Объедините несколько dcast data.table (которые используют один и тот же ключ) эффективно

set.seed(10); 
DT = data.table(GROUP = sample(c("a","b","c"),100,replace = T), 
       ADVANCED = sample(c("ADVANCED","DROP"),100,replace = T), 
       GRADE = sample(1:10,100, replace=T)) 

    GROUP ADVANCED GRADE 
    1:  b ADVANCED  3 
    2:  a ADVANCED  6 
    3:  b ADVANCED  7 
    4:  c ADVANCED  9 

95:  b  DROP  6 
96:  c ADVANCED  5 
97:  a  DROP 10 
98:  b ADVANCED  1 
99:  c  DROP  6 
100:  a  DROP  2 
    GROUP ADVANCED GRADE 

по существу здесь результат я ищу:

result = merge(
    dcast.data.table(DT,.Primitive("~")(GROUP,ADVANCED)), 
    dcast.data.table(DT,.Primitive("~")(GROUP,.), 
        value.var="GRADE", 
        fun.aggregate=median)); 

setnames(result,".","MEDIAN_GRADE") 

    GROUP ADVANCED DROP MEDIAN_GRADE 
1:  a  17 19   6 
2:  b  20 21   7 
3:  c  13 10   6 

Сейчас я интересно, как я могу это сделать без создания двух отдельных таблиц dcast и слияния в конце. Я имею дело со многими строками и столбцами в моих таблицах, а группировка по ключевым словам является узким местом. Мне интересно, есть ли лучший способ рассчитать это?

** Поскольку мой первый вопрос был неопределенным, я полностью редактирую (спасибо Фрэнку и Акруну за их отзывы).

+0

Прежде чем создавать случайные примеры, вы должны использовать 'set.seed'. – Frank

+0

Существует 'reshape2 :: dcast (DT, GROUP ~ ADVANCED, marginins =" ​​ADVANCED ")', но вы теряете доступ к улучшениям, сделанным в 'data.table :: dcast'. Похоже, что «поля» никогда не были реализованы: https://github.com/Rdatatable/data.table/issues/1214 – Frank

+0

Это похоже на совершенно другой вопрос из того, который вы опубликовали ранее. – akrun

ответ

2

Для обновленного вопроса

setnames(dcast(DT, GROUP~ADVANCED, length)[dcast(DT, GROUP~., median), 
      on = "GROUP"], ".", "MEDIAN_GRADE")[] 
# GROUP ADVANCED DROP MEDIAN_GRADE 
#1:  a  17 19   6 
#2:  b  20 21   7 
#3:  c  13 10   6 

Или более быстрый подход будет заключаться в группе по 'GROUP', получить median из 'GRADE', а затем сделать присоединиться ondcast выход

DT[,.(MEDIAN_GRADE = median(GRADE)) , .(GROUP)][ 
       dcast(DT, GROUP ~ ADVANCED, length), on = 'GROUP'] 
+2

В общем случае 'dcast (DT, GROUP ~ ADVANCED) [, SIZE: = Уменьшить (\' + \ ', .SD), .SDcols = unique (DT $ ADVANCED)] []' – Frank

+0

действительная функция, которую я Мне интересно, сложнее, и я не могу суммировать все столбцы, чтобы получить это напрямую. Я добавил это к вопросу. спасибо –

+0

@ Махди Это слишком расплывчато для меня, чтобы понять. – Frank

3

Ну, вы могли бы вычислить в длинной форме, а затем изменить форму:

dcast(DT[, rbind(
    .SD[, .(v = .N), by=.(stat = paste0("n.",ADVANCED))], 
    .(stat = "med", v = as.numeric(median(GRADE))) 
), by=GROUP], GROUP ~ stat) 

    GROUP med n.ADVANCED n.DROP 
1:  a 6   17  19 
2:  b 7   20  21 
3:  c 6   13  10 

Очевидно, что это все еще включает тонны ручной игры. Это также требует, чтобы ваши статистические данные были числовыми (поскольку они укладываются в столбец stat вместе до dcast). Я думаю, что подход в ответе @ akrun - вроде DT[, f(...), by=GROUP][dcast(DT, GROUP ~ x), on=GROUP] - намного лучше, ограничивая dcast только теми вызовами, которые в нем нуждаются.