7 Stimmen

R: Aggregiere Spalten eines data.frames

Ich habe ein data.frame, das so aussieht

> head(df)
            Memory    Memory    Memory    Memory    Memory     Naive     Naive
10472501  6.075714  5.898929  6.644946  6.023901  6.332126  8.087944  7.520194
10509163  6.168941  6.495393  5.951124  6.052527  6.404401  7.152890  8.335509
10496091 10.125575  9.966211 10.075613 10.310952 10.090649 11.803949 11.274480
10427035  6.644921  6.658567  6.569745  6.499243  6.990852  8.010784  7.798154
10503695  8.379494  8.153917  8.246484  8.390747  8.346748  9.540236  9.091740
10451763 10.986717 11.233819 10.643245 10.230697 10.541396 12.248487 11.823138  

und ich möchte den Mittelwert der Memory-Spalten und den Mittelwert der Naive-Spalten finden. Die aggregate-Funktion aggregiert Zeilen. Dieses data.frame könnte potenziell eine große Anzahl von Zeilen haben, und daher erscheint es mir schlecht, die Transposition anzuwenden und dann aggregate nach den colnames des originalen data.frames anzuwenden, und ist im Allgemeinen ärgerlich:

> head(t(aggregate(t(df),list(colnames(df)), mean)))
         [,1]       [,2]      
Group.1  "Memory"   "Naive"   
10472501 "6.195123" "8.125439"
10509163 "6.214477" "7.733625"
10496091 "10.11380" "11.55348"
10427035 "6.672665" "8.266854"
10503695 "8.303478" "9.340436"

Was ist die offensichtliche Sache, die ich übersehe?

8voto

JoFrhwld Punkte 8637

Ich bin ein großer Verfechter der Umformatierung von Daten, damit sie im "long" Format vorliegen. Die Nützlichkeit des long Formats wird besonders deutlich, wenn es um Probleme wie dieses geht. Glücklicherweise ist es ziemlich einfach, Daten wie diese mit dem reshape-Paket in fast jedes Format umzuformen.

Wenn ich Ihre Frage richtig verstanden habe, möchten Sie den Mittelwert von Memory und Naive für jede Zeile haben. Aus irgendeinem Grund müssen wir die Spaltennamen für reshape::melt() eindeutig machen.

colnames(df) <- paste(colnames(df), 1:ncol(df), sep = "_")

Dann müssen Sie eine ID-Spalte erstellen. Sie könnten entweder Folgendes tun

df$ID <- 1:nrow(df)

oder, wenn diese Zeilenbezeichnungen sinnvoll sind

df$ID <- rownames(df)

Jetzt, mit dem reshape-Paket

library(reshape)
df.m <- melt(df, id = "ID")
df.m <- cbind(df.m, colsplit(df.m$variable, split = "_", names = c("Measure", "N")))
df.agg <- cast(df.m, ID ~ Measure, fun = mean)

df.agg sollte jetzt Ihrem gewünschten Ausgabeschnipsel entsprechen.

Oder wenn Sie nur die Gesamtmittelwerte über alle Zeilen hinweg möchten, wird Zack's Vorschlag funktionieren. Etwas wie

m <- colMeans(df)
tapply(m, colnames(df), mean)

Sie könnten dasselbe Ergebnis erzielen, aber als DataFrame formatiert mit

cast(df.m, .~variable, fun = mean)

4voto

Jonathan Chang Punkte 23097

Was ist mit so etwas wie

l <-lapply(unique(colnames(df)), function(x) rowMeans(df[,colnames(df) == x]))

df <- do.call(cbind.data.frame, l)

3voto

John Punkte 22733

Um Jonathan Changs Antwort zu klären... das offensichtliche Ding, das dir fehlt, ist, dass du einfach die Spalten auswählen und den Befehl rowMeans ausführen kannst. Das gibt dir einen Vektor der Mittelwerte für jede Zeile. Sein Befehl bekommt die Zeilenmittelwerte für jede Gruppe von eindeutigen Spaltennamen und war genau das, was ich schreiben wollte. Mit deinen Beispieldaten ist das Ergebnis seines Befehls zwei Listen.

rowMeans ist auch sehr schnell.

Um es aufzuschlüsseln, um die Mittelwerte aller deiner Speicherspalten zu erhalten ist nur

rowMeans(df[,colnames(df) == 'Memory']) #oder aus deinem Beispiel, rowMeans(df[,1:5])

Es ist die einfachste vollständig richtige Antwort, gib ihm ein Upvote und markiere ihn als richtig, wenn es dir gefällt.

(Übrigens, ich mochte auch Jos Empfehlung, generell Dinge als Long-Daten zu behalten.)

0voto

mbq Punkte 18256

Ich denke, du hast deine Daten ohne header=TRUE geladen und was du hast, ist eine Faktormatrix, weshalb deine im Allgemeinen gute Idee fehlschlägt.

0voto

Frank Wang Punkte 1278
m = matrix(1:12,3)
colnames(m) = c(1,1,2,2)

m

     1 1 2  2
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12

mt = t(m)
sapply(by(mt,rownames(mt),colMeans),identity)

     1    2
V1 2.5  8.5
V2 3.5  9.5
V3 4.5 10.5

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X