2016-07-10 5 views
2

Ich versuche, meine Datenmenge zu filtern, um doppelte Zeilen loszuwerden. Ich möchte jedoch meinen Filter auf zwei verschiedene Spalten anwenden, die identisch sind, wenn sie invers genommen werden (Origin-Destination-Daten). Hier ist ein Beispiel von Daten:filter distinct Wert basierend auf zwei Spalten mit inversen String-Werten in `r`

data2<-matrix(NA, nrow = 7, ncol=5) 
colnames(data2)<-c("City.Pair", "Origin.City", "Destination.City", "Total.Passengers", "Total.Revenue") 
data2[,1] <- c("LIS-BRU","LIS-LHR","LAD-LIS", "LIS-LAD", "FAO-MAN", "MAN-FAO","LIS-ORY") 
data2[,2]<- c("LISBON", "LISBON", "LUANDA", "LISBON", "FARO", "MANCHESTER", "LISBON") 
data2[,3] <- c("BRUSSELS","LONDON", "LISBON", "LUANDA", "MANCHESTER", "FARO", "PARIS") 
data2[,4] <- c(100, 5000, 200, 200, 4000, 4000, 4000) 
data2[,5] <- c(100.66, 5000.25, 200.75, 200.75, 4000.10, 4000.10, 4000.05) 
data2<-data.frame(data2) 


    City.Pair Origin.City Destination.City Total.Passengers Total.Revenue 
1 LIS-BRU  LISBON   BRUSSELS    100  100.66 
2 LIS-LHR  LISBON   LONDON    5000  5000.25 
3 LAD-LIS  LUANDA   LISBON    200  200.75 
4 LIS-LAD  LISBON   LUANDA    200  200.75 
5 FAO-MAN  FARO  MANCHESTER    4000  4000.1 
6 MAN-FAO MANCHESTER    FARO    4000  4000.1 
7 LIS-ORY  LISBON   PARIS    4000  4000.05 

Ich benutzen die dplyr Bibliothek und distinct, die mit meiner Anzahl der Passagiere und Einnahmen mit dem folgenden Code funktioniert gut:

library(dplyr) 
data4 <- distinct(data2, Total.Passengers, Total.Revenue) 

aber meine wirkliche Datenmenge hat Millionen von Reihen und manchmal die Anzahl der Passagiere für ein Stadtpaar ist nicht genau gleich (Unterschied der Dezimalstellen). Aber ich muss immer noch die Daten filtern und nur einen Datensatz aufbewahren, damit ich die Fahrgäste und die Einnahmen nicht doppelt zähle.

Obwohl, ich bin auf der Suche nach einer Funktion, die es mir ermöglicht, basierend auf dem Ursprung und der Destination oder auf der City.Pair zu filtern.

Als Teil meiner Studien habe ich versucht, die anti_join Funktion zu verwenden, indem Sie eine Verdopplung des Datensatzes zusammenführen, aber es behält alle Zeilen. Ich habe auch mit der union versucht, aber das gleiche Ergebnis.

data3<- data2 
data5<- anti_join(data2, data3, by=c("Origin.City" = "Destination.City", "Destination.City" = "Origin.City")) 

Meine gewünschte Ausgabe sollte in etwa wie folgt sein:

City.Pair Origin.City Destination.City Total.Passengers Total.Revenue 
1 LIS-BRU  LISBON   BRUSSELS    100  100.66 
2 LIS-LHR  LISBON   LONDON    5000  5000.25 
3 LAD-LIS  LUANDA   LISBON    200  200.75 
4 FAO-MAN  FARO  MANCHESTER    4000  4000.1 
5 LIS-ORY  LISBON   PARIS    4000  4000.05 

Was wäre die beste Funktion für die Aufgabe sein? Oder was kann ich in meinem eigentlichen Code korrigieren?

Danke!

EDIT

Wie kann ich den Code ändern andere Bedingung in die Filter aufzunehmen? Nehmen wir an, eine Zeile ist codiert und ich möchte auch eine Teilmenge/Filter basierend auf dieser Spalte. Hier

ist der neue Datenrahmen:

data2<-matrix(NA, nrow = 10, ncol=6) 
colnames(data2)<-c("City.Pair", "Origin.City", "Destination.City", "Total.Passengers", "Total.Revenue", "Code") 
data2[,1] <- c("LIS-BRU","LIS-LHR","LAD-LIS", "LIS-LAD", "FAO-MAN", "MAN-FAO","LIS-ORY","LAD-LIS", "LAD-LIS", "LIS-LAD") 
data2[,2]<- c("LISBON", "LISBON", "LUANDA", "LISBON", "FARO", "MANCHESTER", "LISBON","LUANDA", "LUANDA", "LISBON") 
data2[,3] <- c("BRUSSELS","LONDON", "LISBON", "LUANDA", "MANCHESTER", "FARO", "PARIS","LISBON", "LISBON", "LUANDA") 
data2[,4] <- c(100, 5000, 200, 200, 4000, 4000, 4000, 20, 40, 40) 
data2[,5] <- c(100.66, 5000.25, 200.75, 200.75, 4000.10, 4000.10, 4000.05, 20.5, 40.8, 40.8) 
data2[,6] <- c("F", "G","F", "F", "A", "A", "P", "H", "I", "I") 
data2<-data.frame(data2) 
data2 

    City.Pair Origin.City Destination.City Total.Passengers Total.Revenue Code 
1 LIS-BRU  LISBON   BRUSSELS    100  100.66 F 
2 LIS-LHR  LISBON   LONDON    5000  5000.25 G 
3 LAD-LIS  LUANDA   LISBON    200  200.75 F 
4 LIS-LAD  LISBON   LUANDA    200  200.75 F 
5 FAO-MAN  FARO  MANCHESTER    4000  4000.1 A 
6 MAN-FAO MANCHESTER    FARO    4000  4000.1 A 
7 LIS-ORY  LISBON   PARIS    4000  4000.05 P 
8 LAD-LIS  LUANDA   LISBON    20   20.5 H 
9 LAD-LIS  LUANDA   LISBON    40   40.8 I 
10 LIS-LAD  LISBON   LUANDA    40   40.8 I 

So ist die gewünschte Ausgabe wie folgt sein sollte:

City.Pair Origin.City Destination.City Total.Passengers Total.Revenue Code 
1 LIS-BRU  LISBON   BRUSSELS    100  100.66 F 
2 LIS-LHR  LISBON   LONDON    5000  5000.25 G 
3 LAD-LIS  LUANDA   LISBON    200  200.75 F 
5 FAO-MAN  FARO  MANCHESTER    4000  4000.10 A 
7 LIS-ORY  LISBON   PARIS    4000  4000.05 P 
8 LAD-LIS  LUANDA   LISBON    20   20.50 H 
9 LAD-LIS  LUANDA   LISBON    40   40.80 I 

ich mehrere Versuche bin Durchführung kann aber nicht den Filter auf zwei Säulen an der zuführen gleichzeitig .. Hier ist mein Code:

dat1<- 
    data2 %>% 
    group_by(Code, City.Pair, Origin.City, Destination.City) %>% 
    filter(Origin.City!=Destination.City & Destination.City!=Origin.City) %>% 
    summarise(Passengers=sum(Total.Passengers), 
      Revenue=sum(Total.Revenue)) 

Antwort

0

Wir können die 'City.Pair' geteilt durch '-', sort die Elemente in der list Ausgabe, paste them together to give a vector`, nach Duplikaten ('i1') suchen und den logischen Vektor verwenden, um die Zeilen von 'data2' zu unterteilen.

i1 <- !duplicated(apply(sapply(strsplit(as.character(data2$City.Pair), "-"), 
       sort), 2, paste, collapse="-")) 
data2[i1,] 
# City.Pair Origin.City Destination.City Total.Passengers Total.Revenue 
#1 LIS-BRU  LISBON   BRUSSELS    100  100.66 
#2 LIS-LHR  LISBON   LONDON    5000  5000.25 
#3 LAD-LIS  LUANDA   LISBON    200  200.75 
#5 FAO-MAN  FARO  MANCHESTER    4000  4000.1 
#7 LIS-ORY  LISBON   PARIS    4000  4000.05 

Oder separate mit pmin/pmax

library(dplyr) 
library(tidyr) 
separate(data2, City.Pair, into = c("City", "City2"), remove = FALSE) %>% 
     filter(!duplicated(pmin(City, City2), pmax(City, City2))) %>% 
     select(-City, -City2) 
# City.Pair Origin.City Destination.City Total.Passengers Total.Revenue 
#1 LIS-BRU  LISBON   BRUSSELS    100  100.66 
#2 LIS-LHR  LISBON   LONDON    5000  5000.25 
#3 LAD-LIS  LUANDA   LISBON    200  200.75 
#4 FAO-MAN  FARO  MANCHESTER    4000  4000.1 
#5 LIS-ORY  LISBON   PARIS    4000  4000.05 
+0

Vielen Dank @Akrun verwenden, dies ist sehr hilfreich. Ich habe beide Methoden auf meine Datenprobe getestet und es funktioniert perfekt. Bei meinem großen Datensatz sind die Ergebnisse jedoch unterschiedlich.Ich habe beide Funktionen auf meine Daten angewendet (etwa 400.000 Zeilen) und ihre Ergebnisse sind im Gegenteil. Die Teilmenge mit 'dupliziert 'enthielt nur 42.000 Zeilen, während die mit' getrennt '380.000 Zeilen enthielt. Ich versuche immer noch herauszufinden, welches die richtige Arbeit bei der Eliminierung der Duplikate geleistet hat. Haben Sie nach Ihrem Wissen etwas ähnliches erlebt? Irgendein Hinweis, warum gibt es einen großen Unterschied in der Teilmenge? –

+0

@CatherineGladu Ich habe nicht auf einem großen Datensatz getestet, aber meine Vermutung ist, dass es funktionieren sollte., Überprüfen Sie bitte für einige führende/nachhinein Leerzeichen in den Big Data. Es kann etwas ausmachen. zuerst tun 'data2 $ City.Pair <- trimws (data2 $ City.Pair)' – akrun

+0

danke für die Antwort. Der Unterschied kam nicht aus dem Abstand. In meinem Datensatz habe ich mehrere Linien mit dem gleichen Airport.Pair mit unterschiedlicher Anzahl von Passagieren basierend auf anderen Kriterien. Wie auch immer, die erste Methode hielt nur die ersten Beobachtungen und löschte die anderen. Bevor ich die Methode anwendete, hatte ich meine Daten "gruppenweise" und "zusammenfassen", um keine Informationen zu verlieren. Dann, durch Anwenden der "dupliziert", sind die Ergebnisse genau. –

Verwandte Themen