neue Variable erstellen, die nur für eine Teilmenge der Daten mit 'dplyr' definiert ist

8

Betrachten Sie diese Beispieldaten:

%Vor%

Und diese BEISPIEL-vektorisierte Funktion, die leider immer dann einen Fehler auslöst, wenn eines der Argumente NA

ist %Vor%

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.

%Vor%

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

%Vor%

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):

%Vor%

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.

%Vor%

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).

%Vor%

Und wie Sie sehen können, ist die microbenchmark -Lösung mit dplyr wesentlich langsamer als ihre rowwise und base Rivalen.

    
elikesprogramming 03.04.2016, 22:42
quelle

5 Antworten

2

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:

%Vor%

Beachten Sie, dass die Verwendung von if hier vollkommen sicher ist, da die Eingabe die Länge 1 hat.

    
krlmlr 04.04.2016, 13:03
quelle
5

Sie könnten vielleicht in Erwägung ziehen, data.table zu verwenden, da dplyr derzeit In-Place-Mutation , wonach Sie zu suchen scheinen.

%Vor%     
mtoto 04.04.2016 08:14
quelle
2

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):

%Vor%     
docendo discimus 04.04.2016 18:43
quelle
1

Sie könnten die Funktion für die kompletten Zeilen ausführen und dann die Zeilen mit NA zurückbinden (obwohl dies umständlicher ist als die Methode if ... else ):

%Vor%
%Vor%
    
eipi10 04.04.2016 15:44
quelle
1

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:

%Vor%

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%     
jaimedash 05.04.2016 00:06
quelle

Tags und Links