2015-02-19 5 views
3

мне удалось агрегированных данных успешно используя следующий шаблон:R: группа по с пользовательскими функциями

newdf <- setDT(df)[, list(X=sum(x),Y=max(y)), by=Z] 

Однако, в тот момент я пытаюсь сделать что-то более сложным, хотя код работает, он больше не заполнителей по Z: он, похоже, создает фрейм данных с таким же количеством наблюдений, что и исходный df, поэтому я знаю, что на самом деле не происходит группировки.

Таможенная функция, которую я хотел бы применить, - найти n-квантиль для текущего списка значений, а затем сделать с ней другие вещи. Я видел использование sdcols в другой SO ответа и пытался что-то вроде:

customfunc <- function(dt){ 
q = unname(quantile(dt$column,0.25)) 
n = nrow(dt[dt$column <= q]) 
return(n/dt$someOtherColumn) 
} 
#fails to group anything!!! also rather slow... 
newdf <- setDT(df)[, customfunc(.SD), by=Z, .SDcols=c(column, someOtherColumn)] 

Может кто-то пожалуйста, помогите мне понять, что не так с тем, как я пытаюсь использовать группу, и пользовательские функции? Большое спасибо.

Буквальный пример по запросу:

> df <- data.frame(Z=c("abc","abc","def","abc"), column=c(1,2,3,4), someOtherColumn=c(5,6,7,8)) 
> df 
    Z column someOtherColumn 
1 abc  1    5 
2 abc  2    6 
3 def  3    7 
4 abc  4    8 
> newdf <- setDT(df)[, customfunc(.SD), by=Z, .SDcols=c("column", "someOtherColumn")] 
> newdf 
    Z  V1 
1: abc 0.2000000 
2: abc 0.1666667 
3: abc 0.1250000 
4: def 0.1428571 
> 

Как вы можете видеть, DF не группируются. Там должно быть только две строки: одна для «abc», другая для «def», так как я пытаюсь группировать по Z.

+3

Предоставить воспроизводимый пример – Metrics

+0

Я добавил пример. – rstruck

+1

ваш 'customfunc' возвращает вектор для каждой группы (** не ** одно число), и у вас есть тот вектор для каждой группы, объединенный в единую' data.table' – eddi

ответ

3

Как указано выше, основная проблема заключается в том, что ваша пользовательская функция вызывается внутри цикла и что 'dt$column' загадочно даст вам текущее значение в текущей строке. Вместо этого он дает вам всю колонку (вектор). Функция передается по всей таблице данных, а не по строкам данных.

Таким образом, заменяя значение в операторе возврата чем-то, что представляет , выполняется одно значение. Пример:

customfunc <- function(dt){ 
    q = unname(quantile(dt$column,0.25)) 
    n = nrow(dt[dt$column <= q]) 
    return(n/length(dt$someOtherColumn)) 
} 

> df <- data.frame(Z=c("abc","abc","def","abc"), column=c(1,2,3,4), someOtherColumn=c(5,6,7,8)) 
> df 
    Z column someOtherColumn 
1 abc  1    5 
2 abc  2    6 
3 def  3    7 
4 abc  4    8 
> newdf <- setDT(df)[, customfunc(.SD), by=Z, .SDcols=c("column", "someOtherColumn")] 
> newdf 
    Z  V1 
1: abc 0.3333333 
2: def 1.0000000 

Теперь данные агрегированы правильно.

Смежные вопросы