2014-01-31 11 views
8

Von dem, was ich gelesen habe, verloren * Cast-Operationen in reshape2 ihre result_variable Funktion. Hadley deutet an, plyr für diesen Zweck zu verwenden (indem mehrere Ergebnisspalten an den Eingabedatenrahmen angehängt werden). Wie würde ich die Dokumentation Beispiel erkennen ...reshape2: mehrere Ergebnisse der Aggregationsfunktion?

aqm <- melt(airquality, id=c("month", "day"), na.rm=TRUE) 
cast(aqm, month ~ variable + result_variable, range) 

mit reshape2 (dcast) und plyr (ddply)?

+2

Haben Sie auch 'Namen (Luftqualität) <- tolower (Namen (Luftqualität))' am Anfang ausgeführt? –

+0

Nein, die Spaltennamen sind bereits in Kleinbuchstaben ... es gab keine Notwendigkeit. – mrcalvin

Antwort

13

Diese Frage hat mehrere Antworten, aufgrund der Flexibilität der Pakete 'reshape2' und 'plyr'. Ich werde zeigen, eine der einfachsten Beispiele zu verstehen, hier:

library(reshape2) 
library(plyr) 

aqm <- melt(airquality, id=c("Month", "Day"), na.rm=TRUE) 
aqm_ply <- ddply(aqm, .(Month, variable), summarize, min=min(value), max=max(value)) 
aqm_melt <- melt(aqm_ply, id=c("Month", "variable"), variable.name="variable2") 
dcast(aqm_melt, Month ~ variable + variable2) 

# Month Ozone_min Ozone_max Solar.R_min Solar.R_max Wind_min Wind_max Temp_min Temp_max 
# 1  5   1  115   8   334  5.7  20.1  56  81 
# 2  6  12  71   31   332  1.7  20.7  65  93 
# 3  7   7  135   7   314  4.1  14.9  73  92 
# 4  8   9  168   24   273  2.3  15.5  72  97 
# 5  9   7  96   14   259  2.8  16.6  63  93 

Schritt 1: Lassen Sie uns brechen sie in Schritten. Lassen Sie uns zuerst die Definition von 'aqm' alleine lassen und von den geschmolzenen Daten arbeiten. Dies wird das Beispiel leichter verständlich machen.

aqm <- melt(airquality, id=c("Month", "Day"), na.rm=TRUE) 

#  Month Day variable value 
# 1  5 1 Ozone 41.0 
# 2  5 2 Ozone 36.0 
# 3  5 3 Ozone 12.0 
# 4  5 4 Ozone 18.0 
# ... 
# 612  9 30  Temp 68.0 

Schritt 2: Jetzt wollen wir die 'Wert' Spalte mit 'min' und 'max' Spalten ersetzen. Dies können wir mit der Funktion "ddply" aus dem Paket "plyr" erreichen. Dazu verwenden wir die Funktion 'ddply' (Datenrahmen als Eingabe, Datenrahmen als Ausgabe, daher "dd" -ply). Wir spezifizieren zuerst die Daten.

Und dann geben wir die Variablen an, die wir verwenden wollen, um unsere Daten zu gruppieren, "Monat" und "Variable". Wir verwenden die . Funktion, um direkt auf diese Variablen zu verweisen, anstatt auf die Werte zu verweisen, die sie enthalten.

ddply(aqm, .(Month, variable), 

Jetzt müssen wir eine aggregierende Funktion wählen. Wir wählen die Funktion summarize hier, weil wir Spalten ('Tag' und 'Wert') haben, die wir nicht in unsere endgültigen Daten aufnehmen wollen. Die summarize Funktion entfernt alle ursprünglichen, nicht gruppierenden Spalten.

ddply(aqm, .(Month, variable), summarize, 

Schließlich geben wir die Berechnung für jede Gruppe an. Wir können auf die Spalten des ursprünglichen Datenrahmens ('aqm') verweisen, auch wenn sie nicht in unserem endgültigen Datenrahmen enthalten sind. Dies ist, wie es aussieht:

aqm_ply <- ddply(aqm, .(Month, variable), summarize, min=min(value), max=max(value)) 

# Month variable min max 
# 1  5 Ozone 1.0 115.0 
# 2  5 Solar.R 8.0 334.0 
# 3  5  Wind 5.7 20.1 
# 4  5  Temp 56.0 81.0 
# 5  6 Ozone 12.0 71.0 
# 6  6 Solar.R 31.0 332.0 
# 7  6  Wind 1.7 20.7 
# 8  6  Temp 65.0 93.0 
# 9  7 Ozone 7.0 135.0 
# 10  7 Solar.R 7.0 314.0 
# 11  7  Wind 4.1 14.9 
# 12  7  Temp 73.0 92.0 
# 13  8 Ozone 9.0 168.0 
# 14  8 Solar.R 24.0 273.0 
# 15  8  Wind 2.3 15.5 
# 16  8  Temp 72.0 97.0 
# 17  9 Ozone 7.0 96.0 
# 18  9 Solar.R 14.0 259.0 
# 19  9  Wind 2.8 16.6 
# 20  9  Temp 63.0 93.0 

Schritt 3: Wir können sehen, dass die Daten erheblich reduziert, da die ddply Funktion die Zeilen zusammengefasst hat. Jetzt müssen wir die Daten wieder aufschmelzen, damit wir unsere zweite Variable für den endgültigen Datenrahmen bekommen können. Beachten Sie, dass wir ein neues variable.name Argument angeben müssen, also haben wir keine zwei Spalten namens "variable".

aqm_melt <- melt(aqm_ply, id=c("Month", "variable"), variable.name="variable2") 

    # Month variable variable2 value 
# 1  5 Ozone  min 1.0 
# 2  5 Solar.R  min 8.0 
# 3  5  Wind  min 5.7 
# 4  5  Temp  min 56.0 
# 5  6 Ozone  min 12.0 
# ... 
# 37  9 Ozone  max 96.0 
# 38  9 Solar.R  max 259.0 
# 39  9  Wind  max 16.6 
# 40  9  Temp  max 93.0 

Schritt 4: Und wir können es schließlich alles zusammen wickeln unsere Daten in die endgültige Form gegossen wird.

dcast(aqm_melt, Month ~ variable + variable2) 

# Month Ozone_min Ozone_max Solar.R_min Solar.R_max Wind_min Wind_max Temp_min Temp_max 
# 1  5   1  115   8   334  5.7  20.1  56  81 
# 2  6  12  71   31   332  1.7  20.7  65  93 
# 3  7   7  135   7   314  4.1  14.9  73  92 
# 4  8   9  168   24   273  2.3  15.5  72  97 
# 5  9   7  96   14   259  2.8  16.6  63  93 

Hoffentlich gibt Ihnen dieses Beispiel genug Verständnis für den Einstieg. Beachten Sie, dass eine neue, datenrahmenoptimierte Version des 'plyr' Pakets aktiv unter dem Namen 'dplyr' entwickelt wird, so dass Sie vielleicht bereit sein möchten, Ihren Code in das neue Paket zu konvertieren, nachdem es vollständig flügge geworden ist.

4

Hier ist eine dplyr Lösung, die die erstaunliche %>% Funktion nutzt. Es verwendet auch die Basis-reshape-Funktion, die oft zu wenig genutzt wird (IMHO). Der Code ist selbsterklärend.

library(dplyr) 
airquality %>% 
    melt(c('Month', 'Day')) %>% 
    group_by(Month, variable) %>% 
    summarise(min = min(value, na.rm = T), max = max(value, na.rm = T)) %>% 
    reshape(timevar = 'variable', idvar = 'Month', direction = 'wide') %>% 
    arrange(Month) 
5

Ich denke, dass die anderen Antworten sollten Sie in Bezug auf die zurückgelegt haben, wie die Verwendung von „plyr“ oder „dplyr“ (und ich möchte Sie ermutigen, in diese Richtung weiter suchen).

Für Spaß, hier ist ein Wrapper um dcast, damit Sie mehrere Funktionen angeben können. Es funktioniert nicht mit Funktionen, die mehrere Werte zurückgeben (wie range) und es erfordert, dass Sie eine benannte Liste von Funktionen verwenden.

dcastMult <- function(data, formula, value.var = "value", 
        funs = list("min" = min, "max" = max)) { 
    require(reshape2) 
    if (is.null(names(funs)) | any(names(funs) == "")) stop("funs must be named") 
    Form <- formula(formula) 
    LHS <- as.character(Form[[2]]) 
    if (length(LHS) > 1) LHS <- LHS[-1] 
    temp <- lapply(seq_along(funs), function(Z) { 
    T1 <- dcast(data, Form, value.var = value.var, 
       fun.aggregate=match.fun(funs[[Z]]), fill = 0) 
    Names <- !names(T1) %in% LHS 
    names(T1)[Names] <- paste(names(T1)[Names], names(funs)[[Z]], sep = "_") 
    T1 
    }) 
    Reduce(function(x, y) merge(x, y), temp) 
} 

Es sieht aus wie ein bisschen ein Durcheinander, aber das Ergebnis ist, dass Sie mit der gleichen Syntax-Stick erhalten Sie mit vertraut sind, während mehrere Aggregationsfunktionen immer zu verwenden. Die "Namen" für das funs Argument werden als Suffixe in den resultierenden Namen verwendet. Anonyme Funktionen können wie erwartet angegeben werden, z. B. maxSq = function(x) max(x)^2.

dcastMult(aqm, month ~ variable, value.var="value", 
     funs = list("min" = min, "max" = max)) 
# month ozone_min solar.r_min wind_min temp_min ozone_max solar.r_max wind_max temp_max 
# 1  5   1   8  5.7  56  115   334  20.1  81 
# 2  6  12   31  1.7  65  71   332  20.7  93 
# 3  7   7   7  4.1  73  135   314  14.9  92 
# 4  8   9   24  2.3  72  168   273  15.5  97 
# 5  9   7   14  2.8  63  96   259  16.6  93 
+0

Danke Ich mag das wirklich – Nate

+0

Dies ist eine sehr nette Lösung, aber können Sie Argumente an die 'Spaßes' übergeben, oder irgendwelche anderen Argumente für den 'dcast()' Anruf? Wie könnte es etwas generischer gemacht werden? – landroni

2

Mit dem recent commit zum development version of data.table v1.9.5, können wir mehrere value.var Säulen werfen gleichzeitig (und verwenden auch mehrere Aggregationsfunktionen in fun.aggregate). Bitte beachten Sie ?dcast für mehr und auch die Beispiele Abschnitt.

Hier ist, wie wir dcast verwenden:

require(data.table) # v1.9.5+ 
dt = as.data.table(airquality) 
valvars = c("Ozone", "Solar.R", "Wind", "Temp") 
dcast(dt, Month ~ ., fun=list(min, max), na.rm=TRUE, value.var=valvars) 
# Month ._min_Ozone ._min_Solar.R ._min_Wind ._min_Temp ._max_Ozone ._max_Solar.R ._max_Wind 
# 1:  5   1    8  5.7   56   115   334  20.1 
# 2:  6   12   31  1.7   65   71   332  20.7 
# 3:  7   7    7  4.1   73   135   314  14.9 
# 4:  8   9   24  2.3   72   168   273  15.5 
# 5:  9   7   14  2.8   63   96   259  16.6 
# ._max_Temp 
# 1:   81 
# 2:   93 
# 3:   92 
# 4:   97 
# 5:   93 

Sie können sicher die Warnungen ignorieren.

Verwandte Themen