2015-12-16 14 views
15

Come posso abbinare/raggruppare in modo efficiente gli indici delle righe duplicate?Corrispondenza/gruppo di righe duplicate (indici)

Diciamo che ho questo insieme di dati:

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 

posso trovare tutti gli indici di duplicati (compreso il primo duplicato) utilizzando

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 

ma voglio essere in grado di abbinare questi indici come sotto:

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

Come posso farlo in modo efficiente?

+1

lento ma 'Filtro (funzione (x) di lunghezza (x)> 1, da (dat, as.list (dat), rownames))' – rawr

risposta

14

Ecco una possibilità utilizzando "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 

L'idea di base è quello di creare una colonna che "gruppi" le altre colonne (utilizzando .GRP), così come una colonna che conta il numero di duplicati le righe ci sono (usando .N), quindi filtrando tutto ciò che ha più di un duplicato e mettendo la colonna "GRP" in un list.

9

Possiamo usare dplyr. Usando una metodologia simile al post di @ AnandaMahto, creiamo un nome di colonna indice riga (add_rownames(), raggruppiamo per tutte le colonne, abbiamo filter il set di dati con numero di righe in ciascun gruppo maggiore di 1, summarise il 'rowname' a list e estrarre la colonna 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

Entrambe le soluzioni sono eccellenti (stessa logica che non avrei pensato da solo) ed efficiente. Ho segnato la soluzione di Ananda con il segno di spunta verde come ha prima con la logica. Grazie +1 –

Problemi correlati