Rechercher des indices de lignes dupliquées

La fonction dupliquée dans R effectue une recherche de ligne en double. Si nous voulons supprimer les doublons, il suffit d’écrire df[!duplicated(df),] et les doublons seront supprimés du bloc de données.

Mais comment trouver les indices de données dupliquées? Si duplicated renvoie TRUE sur une ligne, cela signifie que c’est la deuxième occurrence d’une telle ligne dans le bloc de données et que son index peut être facilement obtenu. Comment obtenir l’index de première occurrence de cette ligne? Ou, en d’autres termes, un index avec lequel la ligne dupliquée est identique?

Je pourrais faire une boucle sur data.frame, mais je pense qu’il y a une réponse plus élégante sur cette question.

Cela renvoie un vecteur d’index logique:

 duplicated(df) | duplicated(df[nrow(df):1, ])[nrow(df):1] 

Voici un exemple:

 df <- data.frame(a = c(1,2,3,4,1,5,6,4,2,1)) duplicated(df) | duplicated(df[nrow(df):1, ])[nrow(df):1] #[1] TRUE TRUE FALSE TRUE TRUE FALSE FALSE TRUE TRUE TRUE which(duplicated(df) | duplicated(df[nrow(df):1, ])[nrow(df):1]) #[1] 1 2 4 5 8 9 10 

Mise à jour (basée sur un commentaire):
La complexité de la commande peut être réduite si fromLast = TRUE est utilisé comme argument de fonction. C'est plus facile que de créer deux vecteurs inversés.

 duplicated(df) | duplicated(df, fromLast = TRUE) duplicated(df) | duplicated(df, fromLast = TRUE) #[1] TRUE TRUE FALSE TRUE TRUE FALSE FALSE TRUE TRUE TRUE 

Comment ça marche?

La fonction duplicated est appliquée à la fois au bloc de données d'origine et au bloc de données dans l'ordre inverse des lignes. La sortie de ce dernier est à nouveau inversée. Notez que les premières occurrences des valeurs dupliquées dans les données d'origine sont les dernières occurrences dans la version inversée. Ensuite, les deux vecteurs sont combinés en utilisant | comme un TRUE dans au moins l'un d'entre eux indique une valeur dupliquée.

Si vous utilisez un data.table à clé , vous pouvez utiliser la syntaxe élégante suivante

 library(data.table) DT <- data.table(A = rep(1:3, each=4), B = rep(1:4, each=3), C = rep(1:2, 6), key = "A,B,C") DT[unique(DT[duplicated(DT)]),which=T] 

Déballer

  • DT[duplicated(DT)] sous-ensemble de ces lignes qui sont des doublons.

  • unique(...) renvoie uniquement les combinaisons uniques des lignes dupliquées. Cela traite de tous les cas avec plus d'un duplicata

  • DT[..., which = T] fusionne les lignes dupliquées avec l'original, avec which=T renvoie le numéro de ligne (sans which = T renverrait simplement les données).

Vous pouvez aussi utiliser

  DT[,count := .N,by = list(A,B,C)][count>1, which=T]