2016-09-06 4 views
1

Ich habe eine Liste in R namens Daten. Daten haben Spalten CustID und EndDate.Entfernen Sie doppelte Einträge Liste mit Bedingung in R

Was ich tun möchte, ist die Liste CustID vergleichen, doppelte Einträge mit der gleichen CustID zu finden.

Auf die gefundenen Einträge möchte ich die EndDate vergleichen und den Eintrag mit dem niedrigsten Wert (älteste EndDate) aus der Liste entfernen.

Ich habe keine Ahnung, wie dieses Problem zu nähern, da ich nicht sehr gewöhnt bin mit diesen Funktionen in R. zu arbeiten

+2

Bitte geben Sie ein kleines reproduzierbares Beispiel Ihrer Liste an, z. mit 'dput()' – Jimbou

+4

Ist es eine 'list' oder ein' dat.frame'? Bitte überprüfen Sie [wie ein minimal reproduzierbares Beispiel erstellt wird] (http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) und aktualisieren Sie Ihre Frage –

+0

Um den Grund zu klären @ docendodiscimus fragt dies, weil Listen keine Spalten haben. Es ist also unklar, ob Sie Listenelemente oder Spalten eines data.frames meinen. –

Antwort

1
CustID <- c(seq(1,10,1),seq(1,5,1)) 
EndDate <- c(Sys.Date(),rep(seq(Sys.Date(),Sys.Date()+6, 1),2)) 

# Let's assume you're starting with a list 
data <- list(CustID, EndDate) 

Die Liste sieht wie folgt aus:

[[1]] 
[1] 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 

[[2]] 
[1] "2016-09-06" "2016-09-06" "2016-09-07" "2016-09-08" "2016-09-09" "2016-09-10" "2016-09-11" "2016-09-12" "2016-09-06" 
[10] "2016-09-07" "2016-09-08" "2016-09-09" "2016-09-10" "2016-09-11" "2016-09-12" 
# To make matching CustID and EndDate easy let's change it to a DF 
df1   <- as.data.frame(data) 
colnames(df1) <- c("CustID", "EndDate") 

Die data.frame sieht wie folgt aus:

CustID EndDate 
1  1 2016-09-06 
2  2 2016-09-06 
3  3 2016-09-07 
4  4 2016-09-08 
5  5 2016-09-09 
6  6 2016-09-10 
7  7 2016-09-11 
8  8 2016-09-12 
9  9 2016-09-06 
10  10 2016-09-07 
11  1 2016-09-08 
12  2 2016-09-09 
13  3 2016-09-10 
14  4 2016-09-11 
15  5 2016-09-12 
# Find duplicated CustID 
dupID <- duplicated(df1$CustID) 
dupdf <- df1[df1$CustID %in% df1$CustID[dupID],] 

# Remove the entry with the oldest EndDate for each ID 
res <- data.frame(CustID=NA, EndDate = as.Date(NA)) 

for(i in unique(dupdf$CustID)){ 
    tmp <- dupdf[dupdf$CustID == i, ] 
    res <- rbind(res,tmp[!tmp$EndDate == min(tmp$EndDate),]) 
} 
res <- res[!is.na(res$EndDate),] 

Das Ergebnis (res) hat die wiederholte Kunden-IDs (custID) mit dem ältesten EndDate für jede ID entfernt:

CustID EndDate 
11  1 2016-09-08 
12  2 2016-09-09 
13  3 2016-09-10 
14  4 2016-09-11 
15  5 2016-09-12 

Wenn Sie eine vektorisiert wollen Lösung, die Sie verwenden könnten data.table:

require(data.table) 
dupdf <- data.table(dupdf) 
dupdf[,.(
    EndDate = max(EndDate) 
), by = CustID] 

Ein Vorschlag aus den Kommentaren ist

data <- as.data.frame(data) 
subset(data, as.logical(ave(as.numeric(EndDate), CustID, FUN = function(x) { 
    length(x) == 1L | x != min(x) 
}))) 
+0

Vielen Dank, Sir! –

+0

@P.Berg Glücklich zu helfen!Prost –

+3

Dynamisch wächst ein Objekt in einer Schleife (wie Sie mit "res" tun) ist nicht wirklich empfohlen Praxis –

0

Hier ist eine Lösung ist, das dplyr Paket mit

data <- list(CustID=c(seq(1,10,1),seq(1,5,1),3,3,3), 
     EndDate=c(Sys.Date(), 
        rep(seq(Sys.Date(),Sys.Date()+6, 1),2), 
        Sys.Date()+6, Sys.Date()+6, Sys.Date()+10 
        )) 

#Convert list to data frame and remove oldest duplicates 
data %>% 
    do.call(cbind.data.frame,.) %>% 
    group_by(CustID) %>% 
    summarise_all(funs(last)) %>% 
    ungroup 

ID „3“ erscheint 5-mal mit einem Duplikat an dem Tag, gehen wird gehalten werden. Die Funktion "summarize" reduziert die Gruppierungsvariable (in diesem Fall Clustid) auf eine einzige Beobachtung, abhängig von den übergebenen Argumenten. In diesem Fall behält die "letzte" Funktion die jüngste Beobachtung bei und ignoriert das Duplikat am selben Tag.

Wenn Ihre Daten nicht in chronologischer Reihenfolge sind, ordnen Sie die Daten mit arrange (desc (EndDate)) an.

+0

Wenn Sie mehrere Spalten haben und nicht alle zusammenfassen möchten, dann verwenden Sie summieren (EndDate = last (EndDate)) –

+1

Das Extrahieren des letzten Datums unterscheidet sich von dem Entfernen des ersten Datums, wenn mehr als 2 Einträge pro ID vorhanden sein können. (und du könntest einfach 'data%>% data.frame()%>% ...') –

+0

Meinst du ich sollte sie in chronologischer Reihenfolge ordnen? "ordnen (EndDate)"? Dann könnten die Daten mehrere Einträge nach Kunden-ID haben und auch die Erstbestellung wäre irrelevant. –

Verwandte Themen