Ich versuche, mein Verständnis von Plyr in Dplyr zu übertragen, kann aber nicht herausfinden, wie ich nach mehreren Spalten gruppieren soll.
# make data with weird column names that can't be hard coded
data = data.frame(
asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE),
a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE),
value = rnorm(100)
)
# get the columns we want to average within
columns = names(data)[-3]
# plyr - works
ddply(data, columns, summarize, value=mean(value))
# dplyr - raises error
data %.%
group_by(columns) %.%
summarise(Value = mean(value))
#> Error in eval(expr, envir, enclos) : index out of bounds
Was fehlt mir, um das Plyr-Beispiel in eine dplyr-artige Syntax zu übersetzen?
Edit 2017 : Dplyr wurde aktualisiert, sodass eine einfachere Lösung verfügbar ist. Siehe die aktuell ausgewählte Antwort.
group_by_
jetzt erklärt invignette("nse")
.dots
. Hier ist die Lösung, die aus der folgenden Antwort von @hadley übernommen wurde:df %>% group_by_(.dots=list(quote(asihckhdoydk), quote(a30mvxigxkgh))) %>% summarise(n = n())
Antworten:
Da diese Frage gestellt wurde, fügte dplyr Versionen mit Gültigkeitsbereich von
group_by
( Dokumentation hier ) hinzu. Auf diese Weise können Sie dieselben Funktionen verwenden, mit denen Sieselect
Folgendes tun würden:Die Ausgabe Ihrer Beispielfrage ist wie erwartet (siehe Vergleich mit Plyr oben und Ausgabe unten):
Beachten Sie, dass, da immer
dplyr::summarize
nur eine Gruppierungsebene gleichzeitig entfernt wird, in der resultierenden Tabelle immer noch eine Gruppierung stattfindet (die manchmal später die Leute überraschen kann). Wenn Sie vor unerwartetem Gruppierungsverhalten absolut sicher sein möchten, können Sie%>% ungroup
Ihre Pipeline nach dem Zusammenfassen jederzeit erweitern .quelle
0.7.0
Wird aktualisiert, um das Quote-Unquote-System auch mit mehreren Spalten verfügbar zu machen?.dots
Argumente auchgroup_by()
als solche verwenden :data %>% group_by(.dots = columns) %>% summarize(value = mean(value))
.one_of()
hier etwas zu tun? Ich denke, es ist in diesem Zusammenhang überflüssig, da der Ausdruck in einen Aufruf von eingeschlossen istvars()
.one_of()
ist in diesem Zusammenhang überflüssigvalue_A
undvalue_B
in Ihrer Eingabe, und Sie möchten einen Mittelwert für jede der Spalten basierend auf habengroup_by
? könntest du es einfach tun...summarize(Mean_A = value_A, Mean_B = value_B)
?Um den Code vollständig zu schreiben, hier ein Update zu Hadleys Antwort mit der neuen Syntax:
Ausgabe:
quelle
asihckhdoydk
...dots <- lapply(names(df)[-3], function(x) as.symbol(x))
, um das.dots
Argument zu erstellen.dots=
war der entscheidende Schritt. Könnengroup_by
Sie diese Antwort bearbeiten, wenn jemand genau weiß, warum dies für den Anruf erforderlich ist ? im Moment ist es ein bisschen unergründlich.vignette("nse")
gibt an, dass drei Möglichkeiten zum Zitieren akzeptabel sind: Formel, Zitat und Zeichen. Es sei denn , Sie , die Umwelt besorgt sind sie aus ziehen wird, können Sie wahrscheinlich mit wegkommengroup_by_(.dots=grp_cols)
Die Unterstützung dafür in dplyr ist derzeit ziemlich schwach, irgendwann denke ich, dass die Syntax ungefähr so aussehen wird:
Aber das wird wahrscheinlich eine Weile nicht da sein (weil ich alle Konsequenzen durchdenken muss).
In der Zwischenzeit können Sie Folgendes verwenden
regroup()
: Eine Liste mit Symbolen:Wenn Sie ein Zeichen Vektor von Spaltennamen haben, können Sie sie an die richtige Struktur zu konvertieren ,
lapply()
undas.symbol()
:quelle
as.symbol
löst es. Vielen Dank! Falls es bei der Entwicklung hilft: Dieses Szenario ist für mich sehr verbreitet. Aggregieren Sie ein numerisches Ergebnis über jede Kombination der anderen Variablen.regroup
ist ebenfalls veraltet (mindestens ab Version 0.4.3).Die Zeichenfolgenspezifikation von Spalten in
dplyr
wird jetzt durch Varianten derdplyr
Funktionen unterstützt, deren Namen in einem Unterstrich enden. Entsprechend dergroup_by
Funktion gibt es beispielsweise einegroup_by_
Funktion, die Zeichenfolgenargumente annehmen kann. Diese Vignette beschreibt die Syntax dieser Funktionen im Detail.Das folgende Snippet löst das Problem, das @sharoz ursprünglich gestellt hat, sauber (beachten Sie, dass das
.dots
Argument ausgeschrieben werden muss):(Beachten Sie, dass dplyr jetzt den
%>%
Operator verwendet und%.%
veraltet ist).quelle
Bis dplyr die volle Unterstützung für Zeichenfolgenargumente hat, ist dieser Kern vielleicht nützlich:
https://gist.github.com/skranz/9681509
Es enthält eine Reihe von Wrapper-Funktionen wie s_group_by, s_mutate, s_filter usw., die Zeichenfolgenargumente verwenden. Sie können sie mit den normalen dplyr-Funktionen mischen. Beispielsweise
quelle
Es funktioniert, wenn Sie die Objekte übergeben (naja, Sie sind es nicht, aber ...) und nicht als Zeichenvektor:
wo
df
war Ihrdata
.?group_by
sagt:was ich so interpretiere, dass es nicht die Zeichenversionen der Namen bedeutet, sondern wie Sie sich darauf beziehen würden
foo$bar
;bar
wird hier nicht zitiert. Oder wie Sie auf Variablen in einer Formel verweisen würden :foo ~ bar
.@Arun erwähnt auch, dass Sie tun können:
Sie können jedoch nicht etwas übergeben, das nicht bewertet ist und kein Name einer Variablen im Datenobjekt ist.
Ich nehme an, dass dies auf die internen Methoden zurückzuführen ist, mit denen Hadley die Dinge nachschlägt, die Sie über das
...
Argument übergeben.quelle
quelle
Ein (winziger) Fall, der in den Antworten fehlt, den ich explizit machen wollte, ist, wenn die Variablen, nach denen gruppiert werden soll, dynamisch in einer Pipeline generiert werden:
Dies zeigt im Wesentlichen, wie
grep
in Verbindung mit verwendet werdengroup_by_(.dots = ...)
, um dies zu erreichen.quelle
Allgemeines Beispiel für die Verwendung des
.dots
Arguments als Zeichenvektoreingabe für diedplyr::group_by
Funktion:Oder ohne einen fest codierten Namen für die Gruppierungsvariable (wie vom OP angefordert):
Am Beispiel des OP:
Siehe auch die dplyr-Vignette zur Programmierung, in der Pronomen, Quasiquotation, Quosures und Tidyeval erklärt werden.
quelle