Свернуть фрейм данных по группам, используя разные функции для каждой переменной

Определять

df<-read.table(textConnection('egg 1 20 a
                        egg 2 30 a
                        jap 3 50 b
                        jap 1 60 b'))

s.t.

> df
   V1 V2 V3 V4
1 egg  1 20  a
2 egg  2 30  a
3 jap  3 50  b
4 jap  1 60  b

В моих данных нет множителей, поэтому я конвертирую множители в символы:

> df$V1 <- as.character(df$V1)
> df$V4 <- as.character(df$V4)  

Я хотел бы «свернуть» фрейм данных, сохранив V1:

  • Максимум V2
  • Среднее значение V3
  • Режим V4 (это значение на самом деле не меняется в группах V1, так что first, last и т. д. также могут меняться).

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

В этом случае я бы хотел, чтобы вывод формы:

> df.collapse
   V1 V2 V3 V4
1 egg  2 25  a
2 jap  3 55  b

person Fred    schedule 28.06.2011    source источник


Ответы (2)


пакет plyr поможет вам:

library(plyr)
ddply(df, .(V1), summarize, V2 = max(V2), V3 = mean(V3), V4 = toupper(V4)[1])

Поскольку у R нет функции режима (наверное), я ставлю другую функцию. Но легко реализовать функцию режима.

person kohske    schedule 28.06.2011
comment
Спасибо! Кратко и очень полезно +1 - person Fred; 28.06.2011

Я бы предложил использовать ddply из plyr:

require(plyr)
ddply(df, .(V1), summarise, V2=max(V2), V3=mean(V3), V4=V4[1])

Вы можете заменить функции любым вычислением, которое пожелаете. Ваш столбец V3 не является числовым, поэтому может потребоваться преобразовать его в числовое, а затем вычислить режим. Пока я просто возвращаю значение V3 первой строки для каждого из разделений. Или, если вы не хотите использовать plyr:

do.call(rbind, lapply(split(df, df$V1), function(x) {
    data.frame(V2=max(x$V2), V3=mean(x$V3), V4=x$V4[1]))
})
person diliop    schedule 28.06.2011
comment
+1 за альтернативу с использованием do.call. Я не знаю, лучше это или хуже, но приятно знать, что есть другие варианты. - person Fred; 28.06.2011