2017-01-25 6 views
0

Können sagen, wir haben data.frames:Teilmenge eine data.frame basierend auf eindeutigen Kennungen in einem anderen data.frame

x <- data.frame(date=c(1,2,3,1,3), id=c("a", "a", "a", "b", "b"), sum=50:54) 
y <- data.frame(date=c(1,2,1,3), id=c("a", "a", "b", "b")) 

x 
    date id sum 
1 1 a 50 
2 2 a 51 
3 3 a 52 
4 1 b 53 
5 3 b 54 
y 

    date id 
1 1 a 
2 2 a 
3 1 b 
4 3 b 

Nun möchte ich die Zeile in x finden, die Daten hat, die nicht in y, innerhalb derselben ID. In y haben wir 1, 2 und 3 in id a und in y haben wir nur 1 und 2 in id a. Wie identifiziere ich (und entferne vorzugsweise von x) Zeile Nummer 3 in x?

EDIT: Ich fand eine (sehr hässliche und langsame) Lösung, aber es muss eine bessere und schnellere Lösung geben? Momentan läuft es auf zwei großen data.frames, und das erste Mal dauerte es mehr als eine Stunde. Ich muss es mehrmals ausführen, damit jede Hilfe geschätzt wird.

z <- data.frame() 

for (f in 1:length(unique(x$id))) { #Run the iteration for all the unique id's in x 
    id <- unique(x$id)[f] #find the name of the id in this iteriation 
    a <- x[x$id==id,]  #subset x 
    b <- y[y$id==id,]  #subset y 
x.new <- a[a$date%in%unique(b$date),] #find the dates that are in x and also in y 
z <- rbind(z, x.new)  #bind the two data.frames together 
} 

Antwort

2

Es scheint, dass Sie eine wollen innere Verknüpfung. Sie verstehen das Problem als "finden Sie Zeilen in X, die nicht in Y sind, dann entfernen Sie sie aus X", - dies wird häufiger als angegeben "behalten Sie nur Zeilen in X, die auch in Y sind."

Es gibt viele Möglichkeiten, dies zu tun, ist es die Standardeinstellung für base::merge

merge(x, y, all = F) 
# date id sum 
# 1 1 a 50 
# 2 1 b 53 
# 3 2 a 51 
# 4 3 b 54 

Es gibt viele andere Optionen in dem R-FAQ detaillierten How to join (merge) data frames (inner, outer, left, right)?

Wenn Sie das tun müssen, um identifizieren Entfernte Zeilen für einen anderen Zweck, dplyr::anti_join ist ein Weg. anti_join(x, y) gibt die Zeilen in x zurück, die nicht in y sind.

library(dplyr) 
anti_join(x, y) 
# Joining, by = c("date", "id") 
# date id sum 
# 1 3 a 52 

Wenn die Geschwindigkeit ist ein Problem, die data.table Lösung Methode as in this answer wird am schnellsten. This answer does some fairly comprehensive benchmarking. Allerdings macht Ihr Code genug ineffiziente Schritte (wächst ein Datenrahmen in einer Schleife, die gleichen unique Werte, manchmal unnötig neu), dass meine Schätzung ist, dass sogar base::merge mehrere Größenordnungen schneller sein wird.

Verwandte Themen