2016-03-23 5 views
4

Konvertieren Sie sich das folgende interaktive Beispiel, das eine Übersichtstabelle erzeugt:eine Auswertungsfunktion auf Nicht-Standard-Auswertung NSE in dplyr

library(dplyr) 

tg <- ToothGrowth 
ci_int <- 0.95 

tg %>% 
    group_by(supp, dose) %>% 
    summarise(N = n(), 
      mean = mean(len, na.rm = T), 
      sd = sd(len, na.rm = T), 
      se = sd/sqrt(N), 
      ci = se * qt(ci_int/2 + 0.50, N - 1)) 

#  supp dose  N mean  sd  se  ci 
# (fctr) (dbl) (int) (dbl) (dbl)  (dbl) (dbl) 
# 1  OJ 0.5 10 13.23 4.459709 1.4102837 3.190283 
# 2  OJ 1.0 10 22.70 3.910953 1.2367520 2.797727 
# 3  OJ 2.0 10 26.06 2.655058 0.8396031 1.899314 
# 4  VC 0.5 10 7.98 2.746634 0.8685620 1.964824 
# 5  VC 1.0 10 16.77 2.515309 0.7954104 1.799343 
# 6  VC 2.0 10 26.14 4.797731 1.5171757 3.432090 

Ich möchte dies auf eine Funktion und abstrakt konvertieren weg data.frame, measure variable , groupvars Gruppierungsvariablen und die conf.int. Hier ist ein Anfang:

library(lazyeval) 

summarySE <- function(df, measure, groupvars, conf.int = 0.95) { 
    summary_dots <- list(
    ~ n(), 
    interp(~ mean(var, na.rm = T), var = as.name(measure)), 
    interp(~ sd(var, na.rm = T), var = as.name(measure)) 
) 

    df %>% 
    group_by_(.dots = groupvars) %>% 
    summarise_(.dots = setNames(summary_dots, c("N", "mean", "sd"))) 
} 

summarySE(tg, "len", c("supp", "dose")) 

Welche ergibt:

#  supp dose  N mean  sd 
# (fctr) (dbl) (int) (dbl) (dbl) 
# 1  OJ 0.5 10 13.23 4.459709 
# 2  OJ 1.0 10 22.70 3.910953 
# 3  OJ 2.0 10 26.06 2.655058 
# 4  VC 0.5 10 7.98 2.746634 
# 5  VC 1.0 10 16.77 2.515309 
# 6  VC 2.0 10 26.14 4.797731 

Dies ist jedoch nicht sehr trocken fühlt? Außerdem bin ich mir nicht sicher, wie man se und ci implementieren kann, ohne offenkundig komplex/ausführlich zu werden? Vielleicht gibt es insgesamt einen besseren Ansatz oder vielleicht sollte dieser in mehrere Funktionen aufgeteilt werden?

Wie kann ich die obige Übersichtstabelle auf eine Funktion konvertieren, so dass ich es beliebige Kombination aus einem data.frame mit unterschiedlichen measure und groupvars mit dem „Geist“ von dplyr passieren kann?

Antwort

4

ich wirklich nicht ganz bekommen warum die Berechnung von SE und CI komplizierter ist als das, was Sie bereits getan haben.

Ich habe die ... Argumente verwendet, um Ihre Gruppierungsargumente zu erfassen, da dies etwas einfacher zu verwenden scheint.

Insgesamt habe ich am Ende mit der folgenden Funktion auf:

summarySE <- function(.data, measure, ..., conf.int = 0.95) { 
    dots <- lazyeval::lazy_dots(...) 
    measure <- lazyeval::lazy(measure) 

    summary_dots <- list(
    N = ~ n(), 
    mean = lazyeval::interp(~ mean(var, na.rm = T), var = measure), 
    sd = lazyeval::interp(~ sd(var, na.rm = T), var = measure), 
    se = ~ sd/sqrt(N), 
    ci = ~ se * qt(conf.int/2 + 0.50, N - 1)) 

    .data <- dplyr::group_by_(.data, .dots = dots) 
    dplyr::summarise_(.data, .dots = summary_dots) 
} 

Sie diese in eine SE und NSE-Version machen könnte, wenn Sie möchten (und wie Hadley tun könnte).

Verbrauch:

summarySE(tg, len, supp, dose) 

Source: local data frame [6 x 7] 
Groups: supp [?] 

    supp dose  N mean  sd  se  ci 
    (fctr) (dbl) (int) (dbl) (dbl)  (dbl) (dbl) 
1  OJ 0.5 10 13.23 4.459709 1.4102837 3.190283 
2  OJ 1.0 10 22.70 3.910953 1.2367520 2.797727 
3  OJ 2.0 10 26.06 2.655058 0.8396031 1.899314 
4  VC 0.5 10 7.98 2.746634 0.8685620 1.964824 
5  VC 1.0 10 16.77 2.515309 0.7954104 1.799343 
6  VC 2.0 10 26.14 4.797731 1.5171757 3.432090 
+0

Überprüfen Sie die Nutzung. Funktioniert es jetzt? – Axeman

+0

Ja, ich passierte 'supp' und 'dose' als Vektor,' c (supp, dose) '- Ich habe immer Angst,' '' '' 'zu verwenden - gibt es eine schnelle Alternative, um diese als zu übergeben 'Gruppe = c (...)'? – JasonAizkalns

+1

Sie werden die 'Lazy_Dots' los. Verwenden Sie dann eine Liste für die Gruppierungsvariablen und füttern Sie diese direkt an 'group_by_'. Sie müssen jedoch zitiert werden. Z.B. 'summarySE (tg, len, liste (~ supp, ~ dose))'. Ich kann nicht herausfinden, wie man eine Liste nackter Namen in eine Liste fauler Objekte auflöst. – Axeman

1

Ich bin mir nicht sicher, dass dies mehr mit dem „Geist“ ist von dplyr, aber man könnte auch versuchen, Strings zu verwenden mean zu berechnen, sd, etc:

summarySE <- function(df, measure, groupvars, conf.int = 0.95) { 
    df %>% group_by_(.dots = groupvars)%>% 
    summarise_(N="n()", 
       mean = paste0("mean(",measure,", na.rm = T)"), 
       sd = paste0("sd(",measure,", na.rm = T)"), 
       se = "sd/sqrt(N)", 
       ci = paste0("se * stats::qt(",conf.int,"/2 + 0.50, N - 1)")) 
} 

summarySE(tg, "len", c("supp", "dose")) 

# supp dose  N mean  sd  se  ci 
# (fctr) (dbl) (int) (dbl) (dbl)  (dbl) (dbl) 
#1  OJ 0.5 10 13.23 4.459709 1.4102837 3.190283 
#2  OJ 1.0 10 22.70 3.910953 1.2367520 2.797727 
#3  OJ 2.0 10 26.06 2.655058 0.8396031 1.899314 
#4  VC 0.5 10 7.98 2.746634 0.8685620 1.964824 
#5  VC 1.0 10 16.77 2.515309 0.7954104 1.799343 
#6  VC 2.0 10 26.14 4.797731 1.5171757 3.432090