2016-06-20 16 views
0

Ich habe folgende Daten-Set:Filtern eines Datensatzes nach grepl in R?

USERNAME API_TRACK_EVENT   TIME 
userA Viewed pic    1454941960 
userA Order/payment   1454941972 
userA Order/Changed Address 1454941976 
userB Viewed pic    1454941983 
userB Order/guestlogin  1454941986 
userB Order/Changed Address 1454941992 

Ich möchte nur die frühere "Order" nehmen, die "Order/Zahlung" für userA und "Order/guestlogin" für userB bedeutet.

Nachdem dies gesagt wurde, sollten alle anderen Nicht-Order-Ereignisse gleich bleiben.

So würde die Ausgabe-Dataset sein:

USERNAME API_TRACK_EVENT   TIME 
userA Viewed pic    1454941960 
userA Order/payment   1454941972 
userB Viewed pic    1454941983 
userB Order/guestlogin  1454941986 

Also, wie soll ich das tun? [Öffnen Sie, um dplyr auch zu verwenden.]

Antwort

3

Hier ist eine Option mit Basis R:

0) bestellen die Daten gemäß USERNAME und TIME:

df <- df[order(df$USERNAME, df$TIME),] 

a) Prüfen, ob Zeilen Reihenfolge-Informationen enthalten:

idx <- grepl("Order", df$API_TRACK_EVENT, ignore.case = TRUE) 

b) Subset von einer Gruppe von NUTZERNAME

subset(df, ave(idx, USERNAME, FUN = cumsum) <= 1L | !idx) 

# USERNAME API_TRACK_EVENT  TIME 
#1 userA  Viewed_pic 1454941960 
#2 userA Order/payment 1454941972 
#4 userB  Viewed_pic 1454941983 
#5 userB Order/guestlogin 1454941986 

This Teilmengen nur der erste Auftrag-Reihe und alle anderen Reihen (ohne Bestellinfo).

+0

Entschuldigung, dass ich das Detail verpasste, dass die Reihen Bestellung sein müssen. zu "Zeit" und der früheste sollte in dem resultierenden Datensatz existieren. Danke an Ihren Kommentar zu der anderen Antwort, ich habe mich an den Fehler erinnert :) – Dawny33

+0

@ Dawny33, habe ich einen Schritt hinzugefügt, um die Daten zu bestellen –

+0

Danke für solch eine detaillierte Antwort. :) – Dawny33

2

Wir können slice/which.max/grep verwenden, um die Zeilen in dplyr herauszufiltern. Nach Gruppierung nach 'USERNAME' erhalten wir einen logischen Index mit grepl, wickeln ihn mit which.max, um den numerischen Index des ersten TRUE-Werts zu erhalten, verwenden seq, um die Sequenz von 1:index und slice zu erhalten, um die Zeilen zu unterteilen. Bei diesem Ansatz wird davon ausgegangen, dass die "Order" -Elemente am Ende für jeden "USERNAME" auftreten, wie im Beispiel gezeigt.

library(dplyr) 
df1 %>% 
    arrange(USERNAME, TIME) %>% 
    group_by(USERNAME) %>% 
    slice(seq(which.max(grepl("Order", API_TRACK_EVENT)))) 
# USERNAME API_TRACK_EVENT  TIME 
#  <chr>   <chr>  <int> 
#1 userA  Viewed pic 1454941960 
#2 userA Order/payment 1454941972 
#3 userB  Viewed pic 1454941983 
#4 userB Order/guestlogin 1454941986 

Wenn jedoch die „Order“ Elemente nicht bestellt werden, können wir duplicated mit grepl verwenden, um die Reihen zu halten, dass jedes Element hat, die nicht über ‚Order‘ oder nur das erste Element ‚Order‘.

df1 %>% 
    arrange(USERNAME, TIME) %>% 
    group_by(USERNAME) %>% 
    filter({idx = grepl("^Order", API_TRACK_EVENT); 
      !duplicated(idx)|!idx}) 

# USERNAME API_TRACK_EVENT  TIME 
#  <chr>   <chr>  <int> 
#1 userA  Viewed pic 1454941960 
#2 userA Order/payment 1454941972 
#3 userB  Viewed pic 1454941983 
#4 userB Order/guestlogin 1454941986 

HINWEIS: Herausgegeben mit Beiträgen von @docendodiscimus


Oder mit der ersten Methode mit data.table

library(data.table) 
setDT(df1)[df1[order(USERNAME, TIME), .I[seq(which.max(grepl("Order", 
         API_TRACK_EVENT)))], USERNAME]$V1] 
+0

Mögliche Erklärung der letzten Zeile? 'slice (seq (which.max (grep (" Reihenfolge ", API_TRACK_EVENT)))) <- Dies – Dawny33

+0

@akrun (+1) Danke für die Antwort. Welche Veränderung kann vorgenommen werden, wenn sie nach der Zeit geordnet werden muss und die "früheste" nehmen möchte? Sorry für das fehlende Detail im qn :) – Dawny33

+0

@docendodiscimus Danke für den Kommentar. Ich vergaß die '{}' – akrun

Verwandte Themen