Wenn das Rohr Operator %>%
mit Paketen wie dplyr
, ggvis
, dycharts
usw., wie soll ich tun bedingt einen Schritt? Beispielsweise;
step_1 %>%
step_2 %>%
if(condition)
step_3
Diese Ansätze scheinen nicht zu funktionieren:
step_1 %>%
step_2
if(condition) %>% step_3
step_1 %>%
step_2 %>%
if(condition) step_3
Es ist ein langer Weg:
if(condition)
{
step_1 %>%
step_2
}else{
step_1 %>%
step_2 %>%
step_3
}
Gibt es einen besseren Weg ohne all die Redundanz?
Antworten:
Hier ist ein kurzes Beispiel, das das
.
und nutztifelse
:In der
ifelse
, wennY
ist ,TRUE
wenn wird 1 hinzufügen, sonst wird es nur den letzten Wert von zurückzukehrenX
. Das.
ist ein Ersatz, der der Funktion mitteilt, wohin die Ausgabe des vorherigen Schritts der Kette geht, sodass ich sie für beide Zweige verwenden kann.Bearbeiten Wie @BenBolker betonte, möchten Sie möglicherweise nicht
ifelse
, daher hier eineif
Version.Vielen Dank an @Frank für den Hinweis, dass ich
{
Klammern um meineif
und -Anweisungen verwenden sollte, umifelse
die Kette fortzusetzen.quelle
ifelse
scheint für den Kontrollfluss unnatürlich.{}
. Wenn Sie sie beispielsweise nicht hier haben, passieren schlimme Dinge (nur DruckenY
aus irgendeinem Grund):X %>% "+"(1) %>% {if(Y) "+"(1) else .} %>% "*"(5)
add
würde das Beispiel klarer machen.X %>% add(1*Y)
, dass es natürlich nicht die ursprüngliche Frage beantwortet{}
ist, dass Sie das vorhergehende Argument der dplyr-Pipe (auch LHS genannt) mit dem Punkt (.) Verweisen müssen - andernfalls empfängt der bedingte Block das nicht. Streit!Ich denke, das ist ein Fall für
purrr::when
. Fassen wir einige Zahlen zusammen, wenn ihre Summe unter 25 liegt, andernfalls geben wir 0 zurück.when
Gibt den Wert zurück, der sich aus der Aktion der ersten gültigen Bedingung ergibt. Stellen Sie die Bedingung links davon~
und die Aktion rechts davon. Oben haben wir nur eine Bedingung (und dann einen anderen Fall) verwendet, aber Sie können viele Bedingungen haben.Sie können das einfach in ein längeres Rohr integrieren.
quelle
Hier ist eine Variation der Antwort von @JohnPaul. Diese Variante verwendet die
`if`
Funktion anstelle einer zusammengesetztenif ... else ...
Anweisung.Beachten Sie, dass in diesem Fall die geschweiften Klammern weder um die
`if`
Funktion noch um eineifelse
Funktion benötigt werden - nur um dieif ... else ...
Anweisung. Wenn der Punktplatzhalter jedoch nur in einem verschachtelten Funktionsaufruf angezeigt wird , leitet magrittr standardmäßig die linke Seite in das erste Argument der rechten Seite weiter. Dieses Verhalten wird überschrieben, indem der Ausdruck in geschweiften Klammern eingeschlossen wird. Beachten Sie den Unterschied zwischen diesen beiden Ketten:Der Punktplatzhalter ist in einem Funktionsaufruf beide Male verschachtelt
`if`
, wenn er in der Funktion angezeigt wird , da. + 1
und. + 2
als`+`(., 1)
bzw. interpretiert`+`(., 2)
werden. Der erste Ausdruck gibt also das Ergebnis von zurück`if`(1, TRUE, 1 + 1, 1 + 2)
(seltsamerweise`if`
beschwert er sich nicht über zusätzliche nicht verwendete Argumente), und der zweite Ausdruck gibt das Ergebnis von zurück`if`(TRUE, 1 + 1, 1 + 2)
, was in diesem Fall das gewünschte Verhalten ist.Weitere Informationen darüber , wie die magrittr Rohr Operator behandelt den Punkt Platzhalter finden Sie in der Hilfedatei für
%>%
, insbesondere den Abschnitt „Mit dem Punkt für sekundäre Zwecke“.quelle
`ìf`
undifelse
? Sind sie im Verhalten identisch?if
undifelse
ist nicht identisch. Dieifelse
Funktion ist vektorisiertif
. Wenn Sie derif
Funktion einen logischen Vektor zur Verfügung stellen, wird eine Warnung ausgegeben und nur das erste Element dieses logischen Vektors verwendet. Vergleiche`if`(c(T, F), 1:2, 3:4)
mitifelse(c(T, F), 1:2, 3:4)
.X %>% { ifelse(Y, .+1, .+2) }
Es scheint mir am einfachsten, mich ein wenig von den Rohren zurückzuziehen (obwohl ich daran interessiert wäre, andere Lösungen zu sehen), z.
Dies ist eine geringfügige Änderung der Antwort von @ JohnPaul (möglicherweise möchten Sie nicht wirklich
ifelse
, da beide Argumente ausgewertet und vektorisiert werden). Es wäre schön, dies so zu ändern, dass es.
automatisch zurückkehrt, wenn die Bedingung falsch ist ... ( Achtung : Ich denke, das funktioniert, aber ich habe nicht wirklich viel darüber getestet / nachgedacht ...)quelle
Ich mag
purrr::when
und die anderen hier bereitgestellten Basislösungen sind alle großartig, aber ich wollte etwas kompakteres und flexibleres, also habe ich die Funktionpif
(Pipe if) entworfen, siehe Code und Dokument am Ende der Antwort.Argumente können entweder Ausdrücke von Funktionen sein (Formelnotation wird unterstützt), und die Eingabe wird standardmäßig unverändert zurückgegeben, wenn die Bedingung erfüllt ist
FALSE
.Verwendet für Beispiele aus anderen Antworten:
Andere Beispiele:
Funktion
quelle