wake-up-neo.com

Aggregieren Sie ein Datenframe für eine bestimmte Spalte und zeigen Sie eine weitere Spalte an

Ich habe ein Datenframe in R der folgenden Form:

> 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

Ich möchte es nach der Spalte Score mit der Funktion max zusammenfassen

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

  Group.1         x
1       1         3
2       2         4

Ich möchte aber auch die Info-Spalte anzeigen, die dem Maximalwert der Score-Spalte für jede Gruppe zugeordnet ist. Ich habe keine Ahnung, wie das geht. Meine gewünschte Ausgabe wäre:

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

Irgendein Hinweis?

52
jul635

Zunächst teilen Sie die Daten mit split auf:

split(z,z$Group)

Wählen Sie dann für jeden Block die Zeile mit maximaler Punktzahl aus:

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

Reduzieren Sie schließlich wieder auf einen data.frame do.calling rbind:

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

Ergebnis:

  Group Score Info
1     1     3    c
2     2     4    d

Eine Zeile, keine Zaubersprüche, schnell, Ergebnis hat gute Namen =)

36
mbq

Eine Basislösung von R besteht darin, die Ausgabe von aggregate() mit einem merge()-Schritt zu kombinieren. Ich finde die Formelschnittstelle zu aggregate() etwas nützlicher als die Standardschnittstelle, zum Teil, weil die Namen auf der Ausgabe schöner sind.

Der Schritt aggregate() ist

maxs <- aggregate(Score ~ Group, data = dat, FUN = max)

und der merge()-Schritt ist einfach

merge(maxs, dat)

Dies gibt uns die gewünschte Ausgabe:

R> maxs <- aggregate(Score ~ Group, data = dat, FUN = max)
R> merge(maxs, dat)
  Group Score Info
1     1     3    c
2     2     4    d

Sie könnten dies natürlich in einen Einzeiler stecken (der Zwischenschritt war mehr zur Darstellung):

merge(aggregate(Score ~ Group, data = dat, FUN = max), dat)

Der Hauptgrund, warum ich die Formelschnittstelle verwendet habe, ist, dass sie einen Datenrahmen mit der korrekten names für den Zusammenführungsschritt zurückgibt. Dies sind die Namen der Spalten aus dem ursprünglichen Datensatz dat. Die Ausgabe von aggregate() muss die richtigen Namen haben, damit merge() weiß, welche Spalten in den ursprünglichen und aggregierten Datenrahmen übereinstimmen.

Die Standardschnittstelle gibt ungerade Namen, wie auch immer Sie es nennen:

R> aggregate(dat$Score, list(dat$Group), max)
  Group.1 x
1       1 3
2       2 4
R> with(dat, aggregate(Score, list(Group), max))
  Group.1 x
1       1 3
2       2 4

Wir können merge() für diese Ausgaben verwenden, aber wir müssen noch mehr arbeiten, um R mitzuteilen, welche Spalten übereinstimmen.

49
Gavin Simpson

Hier ist eine Lösung, die das Paket plyr verwendet. 

Die folgende Codezeile weist ddply im Wesentlichen an, Ihre Daten zunächst nach Gruppen zu gruppieren, und gibt dann innerhalb jeder Gruppe eine Untermenge zurück, bei der die Punktzahl der maximalen Punktzahl in dieser Gruppe entspricht.

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

  Group Score Info
1     1     3    c
2     2     4    d

Und @SachaEpskamp weist darauf hin, dass dies weiter vereinfacht werden kann:

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

(was auch den Vorteil hat, dass which.max, falls vorhanden, mehrere Max-Zeilen zurückgibt).

13
Andrie

Dazu kann das Paket plyr verwendet werden. Mit der Funktion ddply() können Sie einen Datenrahmen in eine oder mehrere Spalten aufteilen, eine Funktion anwenden und einen Datenrahmen zurückgeben. Mit der Funktion summarize() können Sie die Spalten des aufgeteilten Datenrahmens als Variablen verwenden, um den neuen Datenrahmen/zu erstellen.

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
4
Sacha Epskamp

Zu Gavins Antwort hinzufügen: Vor der Zusammenführung ist es möglich, Aggregate so zu verwenden, dass Eigennamen verwendet werden, wenn das Formel-Interface nicht verwendet wird

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

Eine späte Antwort, aber und nähern Sie sich data.table

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

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

Oder wenn es möglich ist, mehr als eine gleich hohe Punktzahl zu erzielen

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

Beachten Sie das (von ?data.table

.SD ist eine Datentabelle, die die Untermenge der Daten von x für jede Gruppe enthält, ausgenommen die Gruppenspalten

4
mnel

So denke ich baseically an das Problem.

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
3
Roman Luštrik

Ich habe keinen guten Ruf, um die Antwort von Gavin Simpson zu kommentieren, aber ich wollte warnen, dass es einen Unterschied in der Standardbehandlung fehlender Werte zwischen der Standardsyntax und der Formelsyntax für aggregate gibt. 

#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
0
John