2016-11-25 4 views
2

Dieses Problem hat mich ratlos.dplyr 'Objekt nicht gefunden' Median nur

Ich habe folgenden Datenrahmen:

library(dplyr) 

# approximation of data frame 
x <- data.frame(doy = sample(c(seq(200, 300)), 20, replace = T), 
       year = sample(c("2000", "2005"), 20, replace = T), 
       phase = sample(c("pre", "post"), 20, replace = T)) 

und eine einfache 'zusammenfassen' Funktion, die als Variable in dem Spalte Namen nimmt, und funktioniert gut:

getStats <- function(df, col) { 
     col <- as.name(col) 
     df %>% 
     group_by(year, phase) %>% 
     summarize(n = sum(!is.na(col)), 
        mean = mean(col, na.rm = T), 
        sd = sd(col, na.rm = T), 
        se = sd/sqrt(n)) 
} 

> getStats(x, "doy") 
Source: local data frame [4 x 6] 
Groups: year [?] 

    year phase  n mean  sd  se 
    <fctr> <fctr> <int> <dbl> <dbl> <dbl> 
1 2000 post  8 248.625 30.42526 10.75695 
2 2000 pre  2 290.000 14.14214 10.00000 
3 2005 post  5 231.400 32.86031 14.69558 
4 2005 pre  5 274.200 29.79429 13.32441 

Allerdings, wenn ich Ändern Sie die Funktion, um den Median zu erhalten, gibt es einen Fehler zurück:

getStats <- function(df, col) { 
     col <- as.name(col) 
     df %>% 
     group_by(year, phase) %>% 
     summarize(n = sum(!is.na(col)), 
        mean = mean(col, na.rm = T), 
        med = median(col, na.rm = T), # new line 
        sd = sd(col, na.rm = T), 
        se = sd/sqrt(n)) 
    } 

> getStats(x, "doy") 

Error in median (doy, na.rm = TRUE): object "doy" not found 

Ich habe einen Host von Namens- und Positionsänderungen, aber alle ergeben das gleiche Ergebnis: 'median' akzeptiert den Spaltennamen nicht als übergebene Variable. Ich nehme an, ich vermisse etwas so Grundlegendes, dass ich eine Gesichtspalme mache, wenn jemand es mir zeigt, aber in der Zwischenzeit fühle ich mich, als würde ich meinen Verstand verlieren. Ich schätze jede Einsicht!

Antwort

3

kann Ihr proximales Problem sein, dass median keinen ... Argument hat, während mean tut (ich bin nicht sicher, warum sd arbeiten ... vielleicht eine Interaktion zwischen Methoden und ...?)

In jedem Fall IMO ist der richtige Weg, diese Art von Problem zu handhaben ist Standard Auswertung zu verwenden (dh nicht nicht-Standard-Bewertung, dh verwendet summarise_ statt summarise, wie in vignette("nse",package="dplyr") dargestellt):

Illustrieren

, wie dies in der globalen Umgebung arbeitet, anstatt in einer Funktion, aber ich denke, dass sollte keine Rolle spielen ...

col <- "doy" 
funs <- c("n","mean","stats::median","sd","se") 
## put together function calls 
dots <- c(sprintf("sum(!is.na(%s))",col), 
     sprintf("%s(%s,na.rm=TRUE)",funs[2:4],col), 
     "sd/sqrt(n)") 
names(dots) <- gsub("^.*::","",funs) ## ugh 
dots 
##        n       mean 
##    "sum(!is.na(doy))"   "mean(doy,na.rm=TRUE)" 
##      median        sd 
## "stats::median(doy,na.rm=TRUE)"   "sd(doy,na.rm=TRUE)" 
##        se 
##     "sd/sqrt(n)" 

x %>% 
    group_by(year, phase) %>% 
    summarise_(.dots=dots) 

Die einzige hier Ärgerliche ist, dass aus irgendeinem Grunde dplyr nicht median finden es sei denn, ich nenne es stats::median, was bedeutet, dass wir etwas härter arbeiten müssen, um schöne Spaltennamen zu erhalten. Die Standard-Bewertungsmethode ist ein bisschen hässlicher, aber das ist der Preis, den Sie für diese Art von Flexibilität zahlen.

Einbettung dieser in einer Funktion, würde ich wahrscheinlich getStats an einer anderen Stelle abbrechen, dh

getStats <- function(data,col) { 
    ## if you want to pass a string argument instead, remove 
    ## the next line 
    col <- deparse(substitute(col)) 
    funs <- c("n","mean","stats::median","sd","se") 
    dots <- c(sprintf("sum(!is.na(%s))",col), 
     sprintf("%s(%s,na.rm=TRUE)",funs[2:4],col), 
     "sd/sqrt(n)") 
    names(dots) <- gsub("^.*::","",funs) ## ugh 
    summarise_(data,.dots=dots) 
} 

x %>% group_by(year,phase) %>% getStats(doy) 

Dies gibt Ihnen mehr Flexibilität, verschiedene Gruppierungen zu tun ...

+0

ich irrational jubelten bin der Gedanke, dass ich diese Lösung nie selbst gefunden hätte. Danke für die blitzschnelle, gründliche und hilfreiche Antwort. Für diejenigen, die sich mit dem gleichen Problem befassen, beachten Sie, dass das Entfernen der Zeile "deparse" es der obigen Funktion erlaubt, eine String-Variable zu behandeln; h. "getStats (data, colName)", wobei 'colName <-" doy "' ist – Jaywalker