2015-12-16 21 views
15

Wie kann ich die Indizes duplizierter Zeilen effizient zuordnen/gruppieren?Übereinstimmende/gruppierte doppelte Zeilen (Indizes)

Lassen Sie uns sagen, dass ich diesen Datensatz haben:

set.seed(14) 
dat <- data.frame(mtcars[sample(1:5, 14, TRUE), ])[sample.int(14), ] 
rownames(dat) <- NULL 
dat 

##  mpg cyl disp hp drat wt qsec vs am gear carb 
## 1 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 
## 2 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 
## 3 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 
## 4 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 
## 5 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 
## 6 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 
## 7 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 
## 8 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 
## 9 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 
## 10 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 
## 11 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 
## 12 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 
## 13 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 
## 14 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 

ich alle Indizes von Dubletten finden können (einschließlich der ersten Duplikat) mit

which_duplicated <- function(dat){ 
    which(duplicated(dat) | duplicated(dat[nrow(dat):1, ])[nrow(dat):1]) 
} 

which_duplicated(dat) 

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

Aber ich möchte in der Lage sein, entsprechen Diese Indizes sind wie folgt:

list(
    c(2, 13), 
    c(1, 4, 5, 6, 9), 
    c(3, 7, 8, 10, 11) 
) 

Wie kann ich das effizient machen?

+1

langsam, aber 'Filter (function (x) Länge (x)> 1, (dat, as.list (dat), rownames))' – rawr

Antwort

14

Hier ist eine Möglichkeit, mit „data.table“:

library(data.table) 
as.data.table(dat)[, c("GRP", "N") := .(.GRP, .N), by = names(dat)][ 
        N > 1, list(list(.I)), by = GRP] 
## GRP    V1 
## 1: 1  1,4,5,6,9 
## 2: 2   2,13 
## 3: 3 3, 7, 8,10,11 

Die Grundidee ist es, eine Spalte zu erstellen, dass „Gruppen“ die anderen Spalten (mit .GRP) sowie eine Spalte, die zählt, wie viele doppelte Zeilen gibt es (mit .N), dann filtert alles, was mehr als ein Duplikat hat, und setzen Sie die "GRP" -Spalte in eine list.

9

Wir können dplyr verwenden. Mit einer ähnlichen Methode wie @ AnandaMahto Beitrag, erstellen wir eine Zeile Index Spaltenname (add_rownames(), gruppieren nach allen Spalten, wir filter der Datensatz mit der Anzahl der Zeilen in jeder Gruppe größer als 1, summarise der 'rowname' zu einem list und extrahieren Sie diese Spalte list.

library(dplyr) 
add_rownames(dat) %>% 
     group_by_(.dots= names(dat)) %>% 
     filter(n()>1) %>% 
     summarise(rn= list(rowname))%>% 
     .$rn 
#[[1]] 
#[1] "3" "7" "8" "10" "11" 

#[[2]] 
#[1] "2" "13" 

#[[3]] 
#[1] "1" "4" "5" "6" "9" 
+1

Beide Lösungen sind ausgezeichnet (gleiche Logik, die ich nicht hätte gedacht von mir selbst) und effizient. Ich markierte Anandas Lösung mit einem grünen Häkchen, wie er es zuerst mit der Logik getan hat. Danke +1 –