Betrachten Sie diese Beispieldaten:
%Vor% Und diese BEISPIEL-vektorisierte Funktion, die leider immer dann einen Fehler auslöst, wenn eines der Argumente NA
Nun, in der Mitte einer dplyr
-Kette muss ich eine neue Variable mit myfn
erstellen. Diese neue Variable ( var3
) ist nur definiert, wenn var1
und var2
nicht NA
sind.
Daher ist die häufigste Lösung für ähnliche Situationen die Verwendung von ifelse
. So etwas.
Aber das funktioniert in meinem Fall nicht, weil ifelse
sowieso den gesamten Vektor var1
und var2
nach myfn
übergibt und nicht nur den Untervektor, wenn test
FALSE
ist. Und es bricht alles, weil myfn
bricht, wenn ein NA
erhalten wird.
Also, was ist die clevere dplyr
Lösung dafür? (Ich kann mir dafür viele Lösungen vorstellen, ohne dplyr
zu verwenden, aber ich bin nur an einer dplyr
-freundlichen Lösung interessiert)
Es ist mir aufgefallen, dass filter
helfen könnte und tatsächlich mit einem sehr lesbaren und dplyr
y Code arbeitet
Aber dann müsste ich das in einem temporären Objekt speichern, dann var3
in den ursprünglichen Daten erstellen, alle mit NA
und alles wieder in die gleichen Daten einfügen (soweit ich das% co_de kenne %, die einige haben vorgeschlagen existiert nicht, ..., noch).
Um nur die Ausgabe zu illustrieren, die ich möchte, erzeugt dieser Code sie (keine Verwendung von unfilter
überhaupt):
BEARBEITEN:
Ich habe @ krmlrs Lösung akzeptiert, weil es genau das ist, wonach ich gesucht habe: klaren, leicht lesbaren und prägnanten Code, der mühelos in eine dplyr
-Kette integriert werden kann. Für mein Beispiel sieht diese Lösung so aus.
Wie @crlmlr jedoch in seiner Antwort darauf hingewiesen hat, hat der Betrieb Zeile für Zeile Kosten in Bezug auf die Leistung. Für kleine Datensätze oder einmalige Operationen ist es möglicherweise nicht von Bedeutung, aber für größere Datenmengen oder die millionenfache Wiederholung der Operation könnte es beträchtlich sein. Zur Veranschaulichung, hier ist ein Vergleich mit dplyr
und drei Lösungen (Basis, dyplr und data.table) über einen etwas größeren Datensatz (nicht massiv oder so, nur 1000 Zeilen statt 10 in meinem ursprünglichen Beispiel).
Und wie Sie sehen können, ist die microbenchmark
-Lösung mit dplyr
wesentlich langsamer als ihre rowwise
und base
Rivalen.
Wenn Ihre ursprüngliche Funktion nicht vektorisiert ist und bestimmte Eingaben nicht verarbeiten kann, gibt es keinen Leistungsvorteil bei der Vektorisierung mit Vectorize()
. Verwenden Sie stattdessen dplyr::rowwise()
, um Zeile für Zeile zu arbeiten:
Beachten Sie, dass die Verwendung von if
hier vollkommen sicher ist, da die Eingabe die Länge 1 hat.
Sie könnten vielleicht in Erwägung ziehen, data.table
zu verwenden, da dplyr
derzeit In-Place-Mutation , wonach Sie zu suchen scheinen.
Hier sind zwei weitere Optionen, die Sie in dplyr-pipes verwenden können:
a) mit einer temporären Variable
%Vor% b) mit einer Wrapper-Funktion (ohne die ursprüngliche myfn
zu ändern):
Dies ist ein großartiger Fall, um den pythonischen Stil zu akzeptieren, anstatt um Vergebung zu bitten um Erlaubnis bitten.
Sie können dies mit tryCatch
lösen und Condition-Testing ganz vermeiden:
Dann
%Vor%gibt das gewünschte Ergebnis
%Vor%Zusatz
Natürlich ist es eine gute Idee, NA nur mit dem richtigen Fehlertyp zu übergeben, nämlich
%Vor%