Агрегатные таблицы данных по заданному столбцу и вывести еще одну колонку


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

> head(data)
  Group Score Info
1     1     1    a
2     1     2    b
3     1     3    c
4     2     4    d
5     2     3    e
6     2     1    f

Я хотел бы объединить их после С помощью max функции

> aggregate(data$Score, list(data$Group), max)

  Group.1         x
1       1         3
2       2         4

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

  Group.1         x        y
1       1         3        c
2       2         4        d

любой намек?

8 51

8 ответов:

во-первых, вы разделяете данные с помощью split:

split(z,z$Group)

чем, для каждого куска, выберите строку с максимальным счетом:

lapply(split(z,z$Group),function(chunk) chunk[which.max(chunk$Score),])

наконец уменьшить обратно к данным.кадр do.calling rbind:

do.call(rbind,lapply(split(z,z$Group),function(chunk) chunk[which.max(chunk$Score),]))

результат:

  Group Score Info
1     1     3    c
2     2     4    d

одна строка, никаких магических заклинаний, быстро, результат имеет хорошие имена =)

базовое решение R заключается в объединении вывода aggregate() С

вот решение с помощью plyr пакета.

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

library(plyr)
ddply(data, .(Group), function(x)x[x$Score==max(x$Score), ])

  Group Score Info
1     1     3    c
2     2     4    d

и, как указывает @SachaEpskamp, это можно еще больше упростить:

ddply(df, .(Group), function(x)x[which.max(x$Score), ])

(которая также имеет то преимущество, что which.max вернет несколько максимальных строк, если таковые имеются).

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

dat <- read.table(textConnection('Group Score Info
1     1     1    a
2     1     2    b
3     1     3    c
4     2     4    d
5     2     3    e
6     2     1    f'))

library("plyr")

ddply(dat,.(Group),summarize,
    Max = max(Score),
    Info = Info[which.max(Score)])
  Group Max Info
1     1   3    c
2     2   4    d

поздний ответ, но и подход, используя data.table

library(data.table)
DT <- data.table(dat)

DT[, .SD[which.max(Score),], by = Group]

или, если это возможно, чтобы иметь более одного одинаково высокий балл

DT[, .SD[which(Score == max(Score)),], by = Group]

отметить, что (с ?data.table

.SD - это данные.таблица, содержащая подмножество данных x для каждой группы, исключая столбец (ы) группы

чтобы добавить к ответу Гэвина: до слияния можно заставить aggregate использовать собственные имена, когда не используется интерфейс формулы:

aggregate(data[,"score", drop=F], list(group=data$group), mean) 

вот как я baseЯ думаю о проблеме.

my.df <- data.frame(group = rep(c(1,2), each = 3), 
        score = runif(6), info = letters[1:6])
my.agg <- with(my.df, aggregate(score, list(group), max))
my.df.split <- with(my.df, split(x = my.df, f = group))
my.agg$info <- unlist(lapply(my.df.split, FUN = function(x) {
            x[which(x$score == max(x$score)), "info"]
        }))

> my.agg
  Group.1         x info
1       1 0.9344336    a
2       2 0.7699763    e

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

#Create some data with missing values 
a<-data.frame(day=rep(1,5),hour=c(1,2,3,3,4),val=c(1,NA,3,NA,5))
  day hour val
1   1    1   1
2   1    2  NA
3   1    3   3
4   1    3  NA
5   1    4   5

#Standard syntax
aggregate(a$val,by=list(day=a$day,hour=a$hour),mean,na.rm=T)
  day hour   x
1   1    1   1
2   1    2 NaN
3   1    3   3
4   1    4   5

#Formula syntax.  Note the index for hour 2 has been silently dropped.
aggregate(val ~ hour + day,data=a,mean,na.rm=T)
  hour day val
1    1   1   1
2    3   1   3
3    4   1   5