R: row-wise dplyr::mutieren mit Funktion, der einen Daten-frame Reihe und gibt eine Ganzzahl zurück
Ich versuche, mit Rohr mutieren-Anweisung mit einer benutzerdefinierten Funktion. Ich sah diesem wenig ähnlich SO ein post aber vergeblich.
Sagen, ich habe einen Daten-frame wie folgt aus (wobei blob
ist einige variable, die nicht mit der spezifischen Aufgabe, sondern ist Teil der gesamten Daten) :
df <-
data.frame(exclude=c('B','B','D'),
B=c(1,0,0),
C=c(3,4,9),
D=c(1,1,0),
blob=c('fd', 'fs', 'sa'),
stringsAsFactors = F)
Habe ich eine Funktion verwendet, die die Variablennamen so wählen Sie basierend auf dem Wert in der exclude
Spalte und z.B. berechnet eine Summe, die auf die Variablen, die nicht in exclude
(das ist immer ein einzelnes Zeichen).
FUN <- function(df){
sum(df[c('B', 'C', 'D')] [!names(df[c('B', 'C', 'D')]) %in% df['exclude']] )
}
Wenn ich gibt eine einzelne Zeile (Zeile 1) FUN
bekomme ich die erwartete Summe der C
und D
(diejenigen, die nicht erwähnt exclude
), nämlich 4:
FUN(df[1,])
Wie mache ich ähnlich wie in einem Rohr mit mutieren (addieren das Ergebnis zu einer variable s
). Diese zwei versuche funktionieren nicht:
df %>% mutate(s=FUN(.))
df %>% group_by(1:n()) %>% mutate(s=FUN(.))
UPDATE
Das ja auch nicht so funktionieren wie Sie sollen:
df %>% rowwise(.) %>% mutate(s=FUN(.))
Diese Werke von Ursache aber nicht in dplyr ' s mutieren (und die Rohre):
df$s <- sapply(1:nrow(df), function(x) FUN(df[x,]))
- Könnten Sie ein Beispiel geben? Funktioniert nicht:
df %>% rowwise(.) %>% mutate(s=FUN(.))
. Die Antwort von @konvas scheint etwas clumpsy (siehe mein Kommentar zu @konvas s Vorschlag) - Sorry, habe ich missverstanden.Sie tun kann
df %>% rowwise(.) %>% mutate(s=FUN(data.frame(exclude = exclude, B = B, C = C, D = D)))
oderdf %>% rowwise() %>% nest(exclude:D) %>% mutate(s = map_dbl(data, FUN)) %>% unnest()
. Das Problem ist, dassdplyr
nicht natürlich funktionieren auf sub-Daten.frames, sondern in Spalten (D. H. Vektoren). So einige zusätzliche Tricks nötig. - Dies ist mehr, was ich nach ! (Für das Protokoll: es ist
tidyr::nest()
undpurrr::map_dbl()
).
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie verwenden möchten
dplyr
können Sie dies mit Hilferowwise
und Ihre FunktionFUN
.Das gleiche kann erreicht werden durch
group_by
stattrowwise
(wie Sie bereits versucht), aber mitdo
stattmutate
Den Grund
mutate
funktioniert nicht in diesem Fall, ist, dass Sie übergeben die ganze tibble, so dass es wie ein AufrufFUN(df)
.Einer viel effizienteren Weise zu tun, die gleiche Sache ist zwar nur eine matrix-Spalten enthalten, und verwenden Sie dann
rowSums
.%>%
). Der Vorschlag in eine do () - Anweisung scheint sehr (wie du sagst) ineffizient und zustandsbehaftete - es da noch eine einfachere Möglichkeit. Ich könnte mir auch getan haben, sehr viel effizienter (aber dann ist dies nicht mit dplyr mutieren und Rohre):df$s <- sapply(1:nrow(df), function(x) FUN(df[x,]))
.purrr
AnsatzWir können eine Kombination von
nest
undmap_dbl
für diese:Lassen Sie uns brechen, dass unten ein wenig. Zuerst
rowwise
ermöglicht es uns, gelten die jeweils nachfolgende Funktion zur Unterstützung von beliebig komplexen Operationen, die angewendet werden müssen, um jede Zeile.Weiter
nest
wird eine neue Spalte erstellen, die eine Liste mit unseren Daten gefüttert werden inFUN
(die Schönheit der tibbles vs Daten.frames!). Da wir die Anwendung dieserrowwise
jede Zeile enthält eine einzelne Zeile von tibbleexclude:D
.Schließlich verwenden wir
map_dbl
Zuordnung unsererFUN
zu jedem dieser tibbles.map_dbl
über die Familie der anderenmap_*
Funktionen, da unsere geplante Ergebnis numerisch ist (also das doppelte).unnest
gibt unsere tibble, in der mehr standard-Struktur.purrrlyr
AnsatzWährend
purrrlyr
vielleicht nicht so "beliebt" wie seine Elterndplyr
undpurrr
seineby_row
Funktion hat einige Dienstprogramm hier.In deinem obigen Beispiel würden wir nutzen Ihre Daten im Rahmen
df
- und Benutzer-definierte FunktionFUN
in der folgenden Weise:Das ist es! Geben Sie:
Zugegeben, die syntax ist ein wenig seltsam, aber hier ist, wie es bricht:
..f
= die Funktion für jede Zeile.to
= der name der Ausgabespalte, in diesem Falls
.collate
= die Art und Weise sollen die Ergebnisse zusammengefaßt werden, indem die Liste, Zeile oder Spalte. DaFUN
hat nur einen einzigen Ausgang, würden wir in Ordnung sein, um entweder"cols"
oder"rows"
Sehen hier für weitere Informationen über die Verwendung
purrrlyr
...Leistung
Vorwarnung, während ich mag die Funktionalität der
by_row
es ist nicht immer der beste Ansatz für die Leistung!purrr
ist mehr intuitiv, sondern auch bei einer ziemlich großen speed Verlust. Finden Sie unter den folgendenmicrobenchmark
test:Können Sie sehen, dass die
purrrlyr
Ansatz ist schneller als der Ansatz, eine Kombination vondo
mitrowwise
odergroup_by(1:n())
(siehe @konvas Antwort), und eher auf Augenhöhe mit densapply
Ansatz. Aber das Paket ist zwar nicht die intuitive. Die standard -purrr
Ansatz scheint der langsamste, sondern vielleicht auch einfacher, mit zu arbeiten. Verschiedene user-definierte Funktionen können die Geschwindigkeit ändern, um.