2017-07-16 2 views
3

Ich frage mich, ob ein dplyr es entsprichtdplyr entspricht DF [DF == X] <- Y

df <- data.frame(A=1:5,B=2:6,C=-1:3) 
df[df==2] <- 10 

Ich bin auf der Suche nach

df %>% <??> 

Das heißt, eine Aussage das ist verkettbar mit anderen dplyr Verben

+1

Nicht, dass ich weiß, aber haben Sie danach gesucht? Dies scheint vor https://stackoverflow.com/questions/34096162/dplyr-mutate-replace-on-a-subset-of-rows oder https://stackoverflow.com/questions/23078891/how-to- update-values-with-dplyr –

+0

@DavidArenburg Ich versuche immer zu schauen. Bedeutet nicht, dass ich immer erfolgreich bin. Danke für den Link...Könnte sein, die Antwort ist ein weiches * NEIN *, wenn man bedenkt, dass der erste Link eine Funktion dafür geschrieben hat. Der zweite Link mutiert nur für eine einzelne Spalte, sieht aber vielversprechend aus ... – CPak

+0

Ich bin allerdings nicht mit 'dplyr' auf dem neuesten Stand. Es scheint sich täglich zu entwickeln. Ganz zu schweigen davon, dass es ein Teil von 'tidyverse' ist, also müssten Sie wahrscheinlich ungefähr 1K-Funktionen durchlaufen, um sicher zu gehen. Vielleicht hat "magritr" auch etwas zu bieten. In Bezug auf den zweiten Link ist es nur die Standardbasis 'ifelse', ähnlich wie im ersten Link verwenden sie' \

Antwort

7

1) ersetzen Versuchen Sie dies. Es erfordert nur magrittr obwohl dplyr den relevanten Teil des magrittr importiert, so dass es auch mit dplyr arbeiten:

df %>% replace(. == 2, 10) 

geben:

A B C 
1 1 10 -1 
2 10 3 0 
3 3 4 1 
4 4 5 10 
5 5 6 3 

1a) zu überschreiben Beachten Sie, dass die oben ist nicht destruktiv, so wenn Sie df aktualisieren möchten, dann müssen Sie es zuweisen zurück:

df <- df %>% replace(. == 2, 10) 

oder

df %>% replace(. == 2, 10) -> df 

oder magrittr %<>% Operator verwenden, die zweimal df Referenzierung eliminiert:

df %<>% replace(. == 2, 10) 

2) Arithmetik Dies würde auch funktionieren:

df %>% { 10 * (. == 2) + . * (. != 2) } 
+0

Sogar aufgeräumt ... danke – CPak

+0

So ist es nur eine Basis R-Lösung wie in den anderen Links. Ich sehe nichts dplyr hier bezogen (was die Frage war). Weder sehe ich, wie ist es besser als 'ersetzen (df, df == 2, 10)' oder 'df [df == 2] <- 10' –

+2

Ich habe ganz deutlich darauf hingewiesen, dass es nur magrit erfordert % <>% Lösung benötigt nur einen Verweis auf df gegenüber 2 für die Basis. Ich denke, die Absicht der Frage war, wie man es in einer Pipeline macht. –

2

Die Frage des OP ist etwa, wie man Ersetzen Sie Werte mit dplyr, und es wurde dank G. Grothendieck gelöst. Aber ich bin gespannt, wie sich die Leistungen zwischen verschiedenen Ansätzen basierend auf dplyr, data.table und Base R unterscheiden. Also habe ich das folgende Benchmarking entworfen und durchgeführt.

# Load package 
library(dplyr) 
library(data.table) 
library(microbenchmark) 

# Create example data frame 
df <- data.frame(A = 1:5, B = 2:6, C = -1:3) 
# Convert to data.table 
dt <- as.data.table(df) 

# Method 1: Use mutate_all and ifelse 
F1 = function(df){df %>% mutate_all(funs(ifelse(. == 2, 10, .)))} 
# Method 2: Use mutate_all and replace 
F2 = function(df){df %>% mutate_all(funs(replace(., . == 2, 10)))} 
# Method 3: Use replace 
F3 = function(df){df %>% replace(. == 2, 10)} 
# Method 4: Base R data frame assignment 
F4 = function(df){ 
    df[df == 2] <- 10 
    return(df) 
} 

# Benchmarking 
microbenchmark(
    M1 = F1(df), 
    M2 = F2(df), 
    M3 = F3(df), 
    M4 = F4(df), 
    # Same as M4, but use data.table object as input 
    M5 = F4(dt) 
) 

Unit: microseconds 
expr  min   lq  mean  median   uq  max neval 
    M1 8634.974 13028.7975 17224.4669 14907.3735 19496.5275 79750.182 100 
    M2 8925.565 12626.2675 16698.7412 15551.7410 18658.1125 35468.760 100 
    M3 282.252 391.6240 591.2534 553.5980 647.8965 3290.797 100 
    M4 163.578 252.1025 423.7627 349.6080 420.8125 5415.382 100 
    M5 228.367 333.2495 596.1735 440.3775 555.5230 7506.609 100 

Die Ergebnisse zeigen, dass mutata_all mit ifelse (M1) oder replace (M2) sind viel langsamer als andere Ansätze. Verwenden Sie replace mit Rohr (M3) ist schnell, aber immer noch ein bisschen langsamer als Base R (M4). Konvertieren Sie data.frame in data.table und wenden Sie dann die Zuweisungsersatz (M5) ist nicht schneller als M4.

Also, ich denke in diesem Fall, gibt es keine besonderen Anforderungen dplyr Funktionen zu verwenden, weil es nicht schneller ist als Base R-Methode (M4). Es gibt auch keine Notwendigkeit, data.frame in data.table umzuwandeln, wenn der Betrieb des Rohres erwünscht ist. Wir können Rohr mit replace (M3) verwenden. Oder wir können eine Funktion wie F4 definieren und in die Pipe-Operation einfügen.

+0

Danke für die Beinarbeit. Gut zu wissen, wie sie sich in der Leistung stapeln. Nach meiner Erfahrung sind Antworten, die nicht beantwortet werden, * umstritten *, aber ich denke, es verdient einen Blick. – CPak

+1

Idiom Konsistenz trumpelt in der Regel in meiner umfangreichen Erfahrung in der realen Welt "Microsecond Performance" Vorteile – hrbrmstr

+0

@hrbrmstr Ich stimme zu. Idiom Konsistenz hilft Code Lesbarkeit. Für kleine Datenrahmen ist Idiomkonsistenz wichtiger als "Mikrosekundenleistung". Aber wenn es viele Datenrahmen oder einen großen Datenrahmen gibt, könnte "Mikrosekundenleistung" wichtig sein. Wenn ich "in diesem Fall" sage, beziehe ich mich nicht nur auf diesen kleinen Datenrahmen, sondern auf diese Art von allgemeiner Operation. – www

Verwandte Themen