2015-02-18 10 views
5

Im Gegensatz zu Fragen, die ich gefunden habe, möchte ich die einzigartige von zwei Spalten ohne Reihenfolge erhalten.Eindeutige Zeilen, unter Berücksichtigung von zwei Spalten, in R, ohne Reihenfolge

Ich habe eine df:

df<-cbind(c("a","b","c","b"),c("b","d","e","a")) 
> df 
    [,1] [,2] 
[1,] "a" "b" 
[2,] "b" "d" 
[3,] "c" "e" 
[4,] "b" "a" 

in diesem Fall der Zeile 1 und Zeile 4 "Dubletten" in dem Sinne, dass B-A gleich wie B-A ist.

Ich weiß, wie einzigartig der Spalten 1 und 2 zu finden, aber ich würde jede Zeile unter diesem Ansatz einzigartig finden.

+0

Das ist kein data.frame, sondern eine Matrix; Wenn es ein df wäre, würde 'unique (df)' den Trick machen. Versuchen Sie 'df <-data.frame (c (" a "," b "," c "," b "), c (" b "," d "," e "," a "))' zuerst. – Frank

+2

Ich glaube nicht, 'unique (df)' prüft nicht über Spalten hinweg, um zu sehen, dass 'c ('a', 'b') 'ist effektiv das gleiche wie' c ('b', 'a') '(und warum sollte es?). Etwas mehr Arbeit ... – r2evans

Antwort

6

Es gibt viel von Möglichkeiten, dies zu tun, ist hier ein:

unique(t(apply(df, 1, sort))) 
duplicated(t(apply(df, 1, sort))) 

Einer der eindeutigen Zeilen gibt, die andere die Maske gibt.

+0

Dieser Ansatz gibt das erste eindeutige Vorkommen einer Zeile (Zeilen 1,2,3) zurück, gibt aber nicht die doppelten Zeilen (Zeilen 1,4)/eindeutigen Zeilen (2,3) zurück, wie durch definiert das ursprüngliche Plakat. – atreju

0

Wenn alle Elemente Strings sind (hey, auch wenn nicht, und Sie können sie erzwingen), dann besteht ein Trick darin, es als data.frame zu erstellen und einige der dplyr Tricks dazu zu verwenden.

library(dplyr) 
df <- data.frame(v1 = c("a","b","c","b"), v2 = c("b","d","e","a")) 
df$key <- apply(df, 1, function(s) paste0(sort(s), collapse='')) 
head(df) 
## v1 v2 key 
## 1 a b ab 
## 2 b d bd 
## 3 c e ce 
## 4 b a ab 

Die $key Spalte sollten Sie jetzt sagen, die Wiederholungen.

df %>% group_by(key) %>% do(head(., n = 1)) 
## Source: local data frame [3 x 3] 
## Groups: key 
## v1 v2 key 
## 1 a b ab 
## 2 b d bd 
## 3 c e ce 
+1

Dies ist nicht sehr gute Verwendung von 'dplyr'. Ich würde vorschlagen, "distinct" zu betrachten, wenn Sie diesen Weg gehen wollten. Bei einem kleinen Datensatz (100 k Zeilen) dauert dieser Ansatz momentan> 4 Sekunden auf meinem System, während der Ansatz der Basis R ~ 1,3 Sekunden dauert und der Ansatz der data.table ~ 0,03 Sekunden dauert. – A5C1D2H2I1M1N2O1R2T1

+1

Mit 'pmin' und' pmax' kommt die Geschwindigkeit ins Spiel. Eine 'dplyr' Variante meiner' data.table' Antwort läuft bei ~ 0.05 Sekunden. Als Referenz sieht die von mir angesprochene Variante folgendermaßen aus: 'data.frame (df, stringsAsFactors = FALSE)%>% mutate (Schlüssel = paste0 (pmin (X1, X2), pmax (X1, X2), sep = ""))%>% distinct (Schlüssel) ' – A5C1D2H2I1M1N2O1R2T1

+0

Ihr Code ist sicherlich beeindruckend. Ich lerne immer noch die Ins-und-Outs von 'dplyr', was dir offensichtlich erscheinen muss. – r2evans

5

Wenn es nur zwei Spalten ist, können Sie auch pmin und pmax wie folgt verwenden:

library(data.table) 
unique(as.data.table(df)[, c("V1", "V2") := list(pmin(V1, V2), 
         pmax(V1, V2))], by = c("V1", "V2")) 
# V1 V2 
# 1: a b 
# 2: b d 
# 3: c e 

Ein ähnlicher Ansatz "dplyr" verwenden könnte sein:

library(dplyr) 
data.frame(df, stringsAsFactors = FALSE) %>% 
    mutate(key = paste0(pmin(X1, X2), pmax(X1, X2), sep = "")) %>% 
    distinct(key) 
# X1 X2 key 
# 1 a b ab 
# 2 b d bd 
# 3 c e ce 
3

Sie könnten Verwenden Sie igraph, um einen ungerichteten Graphen zu erstellen, und konvertieren Sie ihn anschließend wieder in einen Datenrahmen.

unique(get.data.frame(graph.data.frame(df, directed=FALSE),"edges"))