2016-09-26 4 views
0

Ich versuche, mehrere einzelne Mapply-Anweisungen durch einen einzigen, komprimierten Code zu ersetzen. Ich habe es schließlich mit 3 verschachtelten Mapply-Anweisungen arbeiten lassen, aber das scheint ein bisschen kompliziert zu sein. Ich bin neu von R aus anderen Sprachen, also suche nach etwas Hilfe, um in der R-Mentalität zu denken. Wenn die 3 Aussagen der beste Ansatz ist, kann ich damit leben, aber auf der Suche nach Input. Wenn Sie eine bessere Methode zur Strukturierung von Teilmengen wie diese haben, bin ich ganz Ohr.Verschachtelte Mapply-Anweisungen vereinfachen

payments <- data.frame(
    Amount = sample(5:15,100,replace=TRUE), 
    Tip.Amount = round(runif(100,0,2),2), 
    "A" = sample(c(TRUE,FALSE),100,replace=TRUE), 
    "B" = sample(c(TRUE,FALSE),100,replace=TRUE), 
    "C" = sample(c(TRUE,FALSE),100,replace=TRUE), 
    "D" = sample(c(TRUE,FALSE),100,replace=TRUE), 
    "E" = sample(c(TRUE,FALSE),100,replace=TRUE), 
    "F" = sample(c(TRUE,FALSE),100,replace=TRUE), 
    Date = sample(seq(as.Date("2016-01-01"),as.Date("2016-01-31"),by="day"),100,replace=TRUE) 
) 
employees <- c("A","B","C","D","E","F") 
dots <- lapply(c(employees,"Date"),as.symbol) 

payments.by_date_employee <- payments %>% 
    filter(!is.na(Date),!is.na(Amount)) %>% 
    group_by_(.dots=dots) %>% 
    summarise(Payment.Count=n(), Amount=sum(Amount), 
      Tip.Count=sum(Tip.Amount>=0.01,na.rm=TRUE), Tip.Amount=sum(Tip.Amount,na.rm=TRUE)) %>% 
    ungroup() %>% 
    arrange(Date) 

#long/manual way-------------------------------------------------------------------------------- 
t <- list() 
t[["payments"]][["amount"]] <- mapply(function(name) list({ 
    t.test(subset(payments,payments[[name]]==TRUE)$Amount, 
     subset(payments,payments[[name]]==FALSE)$Amount)$p.value 
}), 
employees) 

t[["payments"]][["count"]] <- mapply(function(name) list({ 
    t.test(subset(payments.by_date_employee,payments.by_date_employee[[name]]==TRUE)$Amount, 
     subset(payments.by_date_employee,payments.by_date_employee[[name]]==FALSE)$Amount)$p.value 
}), 
employees) 

t[["tips"]][["amount"]] <- mapply(function(name) list({ 
    t.test(subset(payments,payments[[name]]==TRUE)$Tip.Amount, 
     subset(payments,payments[[name]]==FALSE)$Tip.Amount)$p.value 
}), 
employees) 

t[["tips"]][["count"]] <- mapply(function(name) list({ 
    t.test(subset(payments.by_date_employee,payments.by_date_employee[[name]]==TRUE)$Tip.Amount, 
     subset(payments.by_date_employee,payments.by_date_employee[[name]]==FALSE)$Tip.Amount)$p.value 
}), 
employees) 
#long/manual way-------------------------------------------------------------------------------- 

#attempt at single mapply statement ------------------------------------------------------------ 
y <- mapply(function(name,type,variable,df,nm) list({ 
    t.test(subset(eval(df),eval(df)[[name]]==TRUE)[[nm]], 
     subset(eval(df),eval(df)[[name]]==FALSE)[[nm]])$p.value}), 
    employees, 
    c("payments","payments","tips","tips"), 
    c("amount","count"), 
    c(quote(payments),quote(payments),quote(payments.by_date_employee),quote(payments.by_date_employee)), 
    c("Amount","Amount","Tip.Amount","Tip.Amount"), 
    SIMPLIFY = FALSE 
) 
#attempt at single mapply statement ------------------------------------------------------------ 

#works but seems convoluted -------------------------------------------------------------------- 
z <- mapply(function(type) list({ 
    mapply(function(variable,df,nm) list({ 
    t[[type]][[variable]] <-mapply(function(name) list({ 
     t.test(subset(eval(df),eval(df)[[name]]==TRUE)[[nm]], 
      subset(eval(df),eval(df)[[name]]==FALSE)[[nm]])$p.value}), 
     employees) 
    }), 
    c("amount","count"), 
    c(quote(payments),quote(payments),quote(payments.by_date_employee),quote(payments.by_date_employee)), 
    c("Amount","Amount","Tip.Amount","Tip.Amount"), 
    SIMPLIFY = FALSE 
) 
}), 
c("payments","tips") 
) 
#works but seems convoluted -------------------------------------------------------------------- 

Antwort

1

Hier ist ein Ansatz, der das Problem in ein paar Schritten unterbricht. Zuerst schreiben eine Funktion, die den Namen eines Datenrahmens nimmt, einen Variablennamen und einem Mitarbeiter-Code und gibt den gewünschten Wert:

ttest <- function(data, varname, employee) { 
    d <- get(data) 
    do.call(t.test, setNames(split(d[[varname]], d[[employee]]), c("x", "y")))$p.value 
} 

Jetzt mapply verwenden Sie die Funktion über Vektoren von Datenrahmen Namen anzuwenden, variable Namen und Mitarbeiter Codes:

out <- mapply(ttest, 
    rep(c("payments", "payments.by_date_employee"), each = length(employees)), 
    c(rep(c("Amount", "Tip.Amount"), each = length(employees) * 2)), 
    employees) 

Jetzt haben wir alle Werte, die wir brauchen. Überprüfen Sie, ob die Werte mit denen aus der Liste identisch sind t:

all.equal(unname(out), unname(unlist(t))) 
# [1] TRUE 

Die übrigen Schritte sind die Werte zu organisieren. Wir können sie in einen Datenrahmen setzen:

d <- data.frame(
    type = rep(c("payments", "tips"), each = length(employees) * 2), 
    variable = rep(c("amount", "count"), each = length(employees), times = 2), 
    employee = rep(employees, times = 4), 
    value = out 
) 
#  type variable employee  value 
# 1 payments amount  A 0.23278642 
# 2 payments amount  B 0.77047594 
# ... 
# 7 payments count  A 0.56123674 
# 8 payments count  B 0.81040604 
# ... 
# 13  tips amount  A 0.92749503 
# 14  tips amount  B 0.08716570 
# ... 
# 23  tips count  E 0.20672583 
# 24  tips count  F 0.23505606 

Ein weiterer Schritt, wenn Sie Ihre Ergebnisse als verschachtelte Liste möchten:

y <- lapply(split(d, d$type), 
    function(x) lapply(split(x, x$variable), 
    function(y) split(y$value, y$employee) 
) 
) 
all.equal(t, y) 
# [1] TRUE 

aktualisieren. Um zusätzliche Werte aus der t.test Ausgabe zu erhalten, zuerst

unsere eigenen ttest Funktion ändern
ttest <- function(data, varname, employee) { 
    d <- get(data) 
    unlist(
    do.call(t.test, setNames(split(d[[varname]], d[[employee]]), c("x", "y")))[c("estimate", "p.value")] 
) 
} 

, wo wir in diesem Fall Werte extrahieren für estimate und p.value (für die Namen von anderen Werten Sie jeden t.test Ausgang inspizieren können, zB . str(t.test(1:3, 4:6)) die unlist Funktion fasst die Werte, die wir abrufen (ursprünglich in Form einer Liste) in einen Vektor

Run mapply wie oben beschrieben;.. nun, das out Objekt ist eine Matrix, eher als ein Vektor Angenommen, wir wollen Fügen Sie die Werte in einen Datenrahmen ein:

d <- data.frame(
    type = rep(c("payments", "tips"), each = length(employees) * 2), 
    variable = rep(c("amount", "count"), each = length(employees), times = 2), 
    employee = rep(employees, times = 4), 
    x.mean = out[1, ], 
    y.mean = out[2, ], 
    p.value = out[3, ] 
) 
     type variable employee x.mean y.mean p.value 
# 1 payments amount  A 10.217391 10.240741 0.9714363 
# 2 payments amount  B 9.960784 10.510204 0.4022349 
# 3 payments amount  C 10.490196 9.959184 0.4153361 
# . ...  ...   
+0

Auf jeden Fall sehen, dass es funktioniert. Versuchen, einen Sinn zu machen, was Sie getan haben, bevor Sie es als korrekt markiert haben. Du machst einige Dinge, die neu für mich sind! – atclaus

+0

Wie empfehlen Sie, zusätzliche Werte aus dem t-test herauszuziehen? Ich suche nach dem x und y mean, damit ich zusammenfassen kann, in welche Richtung der Unterschied besteht ... – atclaus

+0

Siehe Änderungen. –