Bei der Arbeit mit fand plyr
ich es oft nützlich, adply
für Skalarfunktionen zu verwenden, die ich auf jede einzelne Zeile anwenden muss.
z.B
data(iris)
library(plyr)
head(
adply(iris, 1, transform , Max.Len= max(Sepal.Length,Petal.Length))
)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len
1 5.1 3.5 1.4 0.2 setosa 5.1
2 4.9 3.0 1.4 0.2 setosa 4.9
3 4.7 3.2 1.3 0.2 setosa 4.7
4 4.6 3.1 1.5 0.2 setosa 4.6
5 5.0 3.6 1.4 0.2 setosa 5.0
6 5.4 3.9 1.7 0.4 setosa 5.4
Jetzt benutze ich dplyr
mehr und frage mich, ob es einen ordentlichen / natürlichen Weg gibt, dies zu tun? Da dies NICHT das ist, was ich will:
library(dplyr)
head(
mutate(iris, Max.Len= max(Sepal.Length,Petal.Length))
)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len
1 5.1 3.5 1.4 0.2 setosa 7.9
2 4.9 3.0 1.4 0.2 setosa 7.9
3 4.7 3.2 1.3 0.2 setosa 7.9
4 4.6 3.1 1.5 0.2 setosa 7.9
5 5.0 3.6 1.4 0.2 setosa 7.9
6 5.4 3.9 1.7 0.4 setosa 7.9
mdply
in dplyr gibt, und Hadley hat vorgeschlagen, dass sie etwas basierend auf brauen könntendo
. Ich denke, es würde auch hier funktionieren.rowwise()
das sich nach jeder einzelnen Reiheadply
wenn Sie keine Gruppierung verwenden? als seine eng integrierte Funktion heißtgroup_by
NOTsplit_by
Antworten:
Ab dplyr 0.2 (glaube ich)
rowwise()
ist implementiert, so lautet die Antwort auf dieses Problem:Keine
rowwise
AlternativeFünf Jahre (!) Später bekommt diese Antwort immer noch viel Verkehr. Da es gegeben wurde,
rowwise
wird es zunehmend nicht empfohlen, obwohl viele Leute es intuitiv zu finden scheinen. Tun Sie sich selbst einen Gefallen und gehen Sie Jenny Bryans zeilenorientierte Workflows in R mit dem aufgeräumten Material durch, um dieses Thema gut in den Griff zu bekommen.Der einfachste Weg, den ich gefunden habe, basiert auf einem von Hadleys Beispielen mit
pmap
:Mit diesem Ansatz können Sie der Funktion (
.f
) im Inneren eine beliebige Anzahl von Argumenten gebenpmap
.pmap
ist ein guter konzeptioneller Ansatz, da er die Tatsache widerspiegelt, dass Sie bei zeilenweisen Operationen tatsächlich mit Tupeln aus einer Liste von Vektoren (den Spalten in einem Datenrahmen) arbeiten.quelle
plyr
als auchdplyr
Pakete einschließen , verwenden Sie mit ziemlicher Sicherheit das Falsche, esmutate
sei denn, Sie geben ausdrücklich den Umfang andplyr::mutate
.Der idiomatische Ansatz besteht darin, eine entsprechend vektorisierte Funktion zu erstellen.
R
bieten ,pmax
die hier geeignet ist, aber es bietet auchVectorize
als Wrapper fürmapply
ermöglichen, eine vektorisiert beliebige Version einer beliebigen Funktion zu erstellen.Beachten Sie, dass die Implementierung der Vektorisierung in C / C ++ schneller ist, es jedoch kein
magicPony
Paket gibt, das die Funktion für Sie schreibt.quelle
dplyr
Weg gibt ... wie es ohne dplyr einfacher wäre, zBwith(df, Coalesce(a,b))
Vielleicht ist das ein Art der Antwort - nicht dafür verwendendplyr
?magicPony
Paket gibt. SchadeSie müssen nach Zeilen gruppieren:
Dies ist , was das
1
tat inadply
.quelle
dplyr
Experte. Hoffentlich kommt jemand anderes mit etwas Besserem. Beachten Sie, dass ich es ein bisschen aufgeräumt habe1:n()
.group_by(1:n())
Verhalten entsprechen sollte. Wenn am Morgen niemand andere Ideen hat, kreuze ich deine an;)n
: "Diese Funktion ist speziell für jede Datenquelle implementiert und kann nur innerhalb von summate verwendet werden.", Obwohl sie zu funktionieren scheint.Update 2017-08-03
Nachdem Hadley dies geschrieben hatte, änderte er wieder einige Dinge. Die Funktionen, die früher in purrr enthalten waren, befinden sich jetzt in einem neuen gemischten Paket namens purrrlyr , das wie folgt beschrieben wird:
Sie müssen dieses Paket also installieren und laden, damit der folgende Code funktioniert.
Ursprünglicher Beitrag
Hadley ändert häufig seine Meinung darüber, was wir verwenden sollen, aber ich denke, wir sollten zu den Funktionen in purrr wechseln, um die Funktionalität nach Zeilen zu erhalten. Zumindest bieten sie die gleiche Funktionalität und haben fast die gleiche Oberfläche wie
adply
von plyr .Es gibt zwei verwandte Funktionen
by_row
undinvoke_rows
. Mein Verständnis ist, dass Sie verwenden,by_row
wenn Sie Zeilen durchlaufen und die Ergebnisse zum data.frame hinzufügen möchten.invoke_rows
wird verwendet, wenn Sie Zeilen eines data.frame durchlaufen und jede Spalte als Argument an eine Funktion übergeben. Wir werden nur die erste verwenden.Beispiele
Auf diese Weise können wir die Interna sehen (damit wir sehen können, was wir tun), was dem entspricht, mit dem wir es tun
adply
.Fügt standardmäßig
by_row
eine Listenspalte hinzu, die auf der Ausgabe basiert:gibt:
Wenn wir stattdessen a zurückgeben
data.frame
, erhalten wir eine Liste mitdata.frame
s:gibt:
Wie wir die Ausgabe der Funktion hinzufügen, wird durch den
.collate
Parameter gesteuert . Es gibt drei Optionen: Liste, Zeilen, Spalten. Wenn unsere Ausgabe die Länge 1 hat, spielt es keine Rolle, ob wir Zeilen oder Spalten verwenden.beide produzieren:
Wenn wir einen data.frame mit 1 Zeile ausgeben, ist es nur unwichtig, welche wir verwenden:
beide geben:
außer dass die zweite die aufgerufene Spalte hat
.row
und die erste nicht.Wenn unsere Ausgabe länger als Länge 1 ist, entweder als
vector
oder alsdata.frame
mit Zeilen, ist es wichtig, ob wir Zeilen oder Spalten verwenden für.collate
:produziert jeweils:
Unterm Strich also. Wenn Sie die
adply(.margins = 1, ...)
Funktionalität wünschen , können Sie verwendenby_row
.quelle
by_row
ist veraltet und heißt "eine Kombination aus: tidyr :: nest (); dplyr :: mutate (); purrr :: map ()" github.com/hadley/purrrlyr/blob/…Erweiterung der Antwort von BrodieG,
Wenn die Funktion mehr als eine Zeile zurückgibt
mutate()
,do()
muss anstelle von verwendet werden. Um es dann wieder zusammen zu kombinieren, verwenden Sie esrbind_all()
aus derdplyr
Packung.In der
dplyr
Version funktioniert diedplyr_0.1.2
Verwendung1:n()
in dergroup_by()
Klausel bei mir nicht. Hoffentlich wird Hadleyrowwise()
bald implementieren .Testen der Leistung,
es hat die folgenden Ergebnisse:
Dies zeigt, dass die neue
purrr
Version die schnellste istquelle
Etwas wie das?
quelle
dplyr
Lösung für eine Skalarfunktion gibt.wacky.function <- function(col.1, col.2){...}
und danniris.wacky <- wacky.function(iris$Sepal.Length, iris$Petal.Length)
.dplyr
oderplyr
oder verwenden,data.table
sollten Sie versuchen, ihre Redewendungen zu verwenden, damit Ihr Code nicht zu einem schwierig zu teilenden Stilmix wird. Daher die Frage.plyr
Dokumentation lautet: "Plyr ist eine Reihe von Werkzeugen, die häufig auftretende Probleme lösen: Sie müssen ein großes Problem in überschaubare Teile zerlegen, jedes Teil bearbeiten und dann alle Teile wieder zusammensetzen." Dies scheint ein ganz anderes Problem zu sein, für das elementare Spaltenoperationen das beste Werkzeug sind. Dies könnte auch erklären, warum es dafür keinen "natürlichen"plyr
/dplyr
Befehl gibt.