2015-05-07 18 views
5

Wie würde ich über die Verwendung von mutate gehen (meine Vermutung ist, dass ich für Standardauswertung in meinem Fall bin auf der Suche, und damit mutate_, aber ich bin nicht ganz sicher, in diesem Punkt), wenn eine Funktion, die eine Liste von Variablennamen, wie dies akzeptiert:dplyr: Standardauswertung für mutieren mit zitierte Variablennamen

createSum = function(data, variableNames) { 
    data %>% 
    mutate_(sumvar = interp(~ sum(var, na.rm = TRUE), 
          var = as.name(paste(as.character(variableNames), collapse =",")))) 

} 

Hier ist ein MWE, den die Funktion seiner Kernlogik Streifen und zeigt, was ich zu erreichen versuchen:

library(dplyr) 
library(lazyeval) 

# function to make random table with given column names 
makeTable = function(colNames, sampleSize) { 
    liSample = lapply(colNames, function(week) { 
    sample = rnorm(sampleSize) 
    }) 
    names(liSample) = as.character(colNames) 
    return(tbl_df(data.frame(liSample, check.names = FALSE))) 
} 

# create some sample data with the column name patterns required 
weekDates = seq.Date(from = as.Date("2014-01-01"), 
        to = as.Date("2014-08-01"), by = "week") 
dfTest = makeTable(weekDates, 10) 

# test mutate on this table 
dfTest %>% 
    mutate_(sumvar = interp(~ sum(var, na.rm = TRUE), 
          var = as.name(paste(as.character(weekDates), collapse =",")))) 
hier 0

Erwartete Ausgabe ist, was würde zurückgegeben werden:

rowSums(dfTest[, as.character(weekDates)]) 
+0

Sie definieren 'makeTable', rufen aber 'makeDataFrame' auf. Sollen diese die gleiche Funktion haben? Es wäre hilfreich, die Ausgabe zu beschreiben, die Sie für diese Beispieleingabe erwarten (setzen Sie einen Anfangswert für die Daten ist reproduzierbar). – MrFlick

+0

@MrFlick Danke. Der Name der Funktion wurde geändert. Es wird nichts Besonderes erwartet, nur die "Summe" aller Variablen, deren Variablennamen an die Funktion übergeben werden, nach Zeilen. Wird mit der erwarteten Ausgabe aktualisiert. – tchakravarty

Antwort

5

ich denke, das ist, was Sie nach

createSum = function(data, variableNames) { 
    data %>% 
     mutate_(sumvar = paste(as.character(variableNames), collapse ="+")) 
} 
createSum(dfTest, weekDates) 

wo wir lieber nur einen Zeichenwert liefern als interp da kann man nicht Übergeben Sie eine Liste von Namen als einen einzelnen Parameter an eine Funktion. Plus, sum() würde einige unerwünschte Zusammenbrüche tun, weil Operationen nicht in Reihen ausgeführt werden, sie werden in Spalten von Vektoren zu einer Zeit übergeben.

Das andere Problem mit diesem Beispiel ist, dass Sie in Ihrem data.frame check.names=FALSE setzen, was bedeutet, dass Sie Spaltennamen erstellt haben, die keine gültigen Symbole sein können. Sie können Ihre Variablennamen in Back-Zecken ausdrücklich wickeln, wenn Sie

createSum(dfTest , paste0("`", weekDates,"`")) 

mögen, aber im Allgemeinen ist es besser, nicht ungültige Namen zu verwenden.

+0

Danke, das würde funktionieren, aber was wäre, wenn die Funktion kein handliches Operator-Symbol hätte? Zweitens, wie würde ich dann eine Liste von Argumenten namentlich an "..." in einer Funktion übergeben? Die einzigen Beispiele für Standardauswertungen, die ich gesehen habe, betreffen einen Variablennamen. – tchakravarty

+0

Es ist nicht einfach, über das Hypothetische zu sprechen, jede Funktion könnte anders sein. Aber diese Methode der Stringbildung sollte für viele andere Funktionen funktionieren ("sum" ist eine Ausnahme). Nur die Paste könnte aussehen wie 'paste0 (" funname (", einfügen (vars, collapse =", "),") ") – MrFlick

+0

Yeah, wie ich befürchtet habe, sieht das wie eine schreckliche Syntax aus (ohne Schuld!) . Ich glaube nicht, dass ich das Paradigma sehr gut verstehe - ich möchte nur variable Symbole in der Umgebung des 'data_frame' auswerten. Sicherlich gibt es einen besseren Weg, dies zu tun, ohne auf umständliche Ausdruckserstellung oder 'eval (parse (text =)') zurückgreifen zu müssen. – tchakravarty

1

Ich weiß nicht, ob dies ein „offiziell sanktionierte“ dplyr Weg ist, aber dies ist eine Möglichkeit:

weekDates = as.character(weekDates) # more convenient 

dfTest %>% mutate(sumvar = Reduce(`+`, lapply(weekDates, get, .))) 
#or 
dfTest %>% mutate(sumvar = rowSums(as.data.frame(lapply(weekDates, get, .)))) 

Dies trägt möglicherweise erhebliche Leistungseinbußen, je nach Ihrer Nutzung - zusätzlich zu dplyr ist das regelmäßige Kopieren der gesamten Daten, ich denke, es kopiert es auch ein zweites Mal während dieser internen Berechnung. Sie können in data.table nachsehen, um das zusätzliche Kopieren zu vermeiden, indem Sie Spalten an der richtigen Stelle hinzufügen (und .SDcols verwenden, um die zweite Kopie zu vermeiden), + Sie werden wohl bessere Syntax bekommen.

Verwandte Themen