Supprimer les lignes dupliquées


152

J'ai lu un CSVfichier dans un data.frame R. Certaines des lignes ont le même élément dans l'une des colonnes. Je souhaite supprimer les lignes dupliquées dans cette colonne. Par exemple:

platform_external_dbus          202           16                     google        1
platform_external_dbus          202           16         space-ghost.verbum        1
platform_external_dbus          202           16                  localhost        1
platform_external_dbus          202           16          users.sourceforge        8
platform_external_dbus          202           16                    hughsie        1

Je voudrais une seule de ces lignes car les autres ont les mêmes données dans la première colonne.


3
lequel veut-tu? juste le premier? en d'autres termes: voulez-vous conserver googleou localhostou hughsie?
Anthony Damico

Cela n'a pas d'importance pour cette partie de mon analyse statistique. J'essaie seulement de relier le titre du projet (première colonne), le nombre de bogues (deuxième colonne) et le nombre d'organisations sur le projet (troisième colonne).
user1897691

3
cool. jeter les colonnes inutiles et utiliser? unique
Anthony Damico

Réponses:


186

isolez simplement votre bloc de données aux colonnes dont vous avez besoin, puis utilisez la fonction unique: D

# in the above example, you only need the first three columns
deduped.data <- unique( yourdata[ , 1:3 ] )
# the fourth column no longer 'distinguishes' them, 
# so they're duplicates and thrown out.

1
Cela semble fonctionner parfaitement. Pouvez-vous m'expliquer ce qui se passe avec la [,1:3]partie de ce code? Je suis nouveau sur R, c'est pourquoi je demande ce que je ne peux que supposer est une question évidente.
user1897691

6
@ user1897691 marquez-le comme correct alors;) regardez ceci et si vous aimez cela, vérifiez twotorials.com
Anthony Damico

3
Notez que cela supprimera toutes les colonnes à l'exception des trois premières.
GuillaumeL

186

Pour les personnes qui sont venues ici pour rechercher une réponse générale à la suppression des lignes en double, utilisez !duplicated():

a <- c(rep("A", 3), rep("B", 3), rep("C",2))
b <- c(1,1,2,4,1,1,2,2)
df <-data.frame(a,b)

duplicated(df)
[1] FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE

> df[duplicated(df), ]
  a b
2 A 1
6 B 1
8 C 2

> df[!duplicated(df), ]
  a b
1 A 1
3 A 2
4 B 4
5 B 1
7 C 2

Réponse de: Suppression des lignes dupliquées du bloc de données R


Je veux créer une nouvelle varibale qui signale s'il y a un doublon sur une certaine variable presque comme df $ duplicates <- ifelse (cette valeur de lignes dans la colonne a == valeur de ligne précédente dans la colonne a, 1, 0)
jacob

@jacob voir cette question stackoverflow.com/questions/12495345/…
dpel

2
Cela conserve la première valeur apparue et supprime le reste des doublons, non? Ou il supprime les valeurs au hasard?
News_is_Selection_Bias

@alphabetagamma oui, il garde la première valeur apparue
Mehdi Nellen

2
Si vous n'êtes intéressé que par les doublons dans certaines colonnes, disons les cols 1 et 2, nous pouvons utiliserdf[!duplicated(df[, 1:2])]
qwr

82

La fonction distinct()du dplyrpackage effectue une suppression arbitraire des doublons, soit à partir de colonnes / variables spécifiques (comme dans cette question), soit en tenant compte de toutes les colonnes / variables. dplyrfait partie du tidyverse.

Données et package

library(dplyr)
dat <- data.frame(a = rep(c(1,2),4), b = rep(LETTERS[1:4],2))

Supprimer les lignes dupliquées dans une colonne spécifique (par exemple, une colonne a)

Notez que .keep_all = TRUEconserve toutes les colonnes, sinon seule la colonne aserait conservée.

distinct(dat, a, .keep_all = TRUE)

  a b
1 1 A
2 2 B

Supprimez les lignes qui sont des doublons complets d'autres lignes:

distinct(dat)

  a b
1 1 A
2 2 B
3 1 C
4 2 D

Excellente réponse, au fait, .keep_all est pour que ce soit de garder toutes les colonnes, ne doit pas être mélangé avec keepdans pandas.
Jason Goal le

28

Le data.tablepaquet a aussi uniqueet duplicatedméthodes de ses propres avec quelques fonctionnalités supplémentaires.

Les méthodes unique.data.tableet les duplicated.data.tableméthodes ont un byargument supplémentaire qui vous permet de passer respectivement un characterou un integervecteur de noms de colonnes ou leurs emplacements

library(data.table)
DT <- data.table(id = c(1,1,1,2,2,2),
                 val = c(10,20,30,10,20,30))

unique(DT, by = "id")
#    id val
# 1:  1  10
# 2:  2  10

duplicated(DT, by = "id")
# [1] FALSE  TRUE  TRUE FALSE  TRUE  TRUE

Une autre caractéristique importante de ces méthodes est un énorme gain de performances pour des ensembles de données plus volumineux

library(microbenchmark)
library(data.table)
set.seed(123)
DF <- as.data.frame(matrix(sample(1e8, 1e5, replace = TRUE), ncol = 10))
DT <- copy(DF)
setDT(DT)

microbenchmark(unique(DF), unique(DT))
# Unit: microseconds
#       expr       min         lq      mean    median        uq       max neval cld
# unique(DF) 44708.230 48981.8445 53062.536 51573.276 52844.591 107032.18   100   b
# unique(DT)   746.855   776.6145  2201.657   864.932   919.489  55986.88   100  a 


microbenchmark(duplicated(DF), duplicated(DT))
# Unit: microseconds
#           expr       min         lq       mean     median        uq        max neval cld
# duplicated(DF) 43786.662 44418.8005 46684.0602 44925.0230 46802.398 109550.170   100   b
# duplicated(DT)   551.982   558.2215   851.0246   639.9795   663.658   5805.243   100  a 

7

Vous pouvez également utiliser dplyrla distinct()fonction de! Il a tendance à être plus efficace que les options alternatives, surtout si vous avez beaucoup d'observations.

distinct_data <- dplyr::distinct(yourdata)

1
C'est la même réponse que la réponse de Sam Firke, mais avec moins de détails.
qwr

6

la réponse générale peut être par exemple:

df <-  data.frame(rbind(c(2,9,6),c(4,6,7),c(4,6,7),c(4,6,7),c(2,9,6))))



new_df <- df[-which(duplicated(df)), ]

production:

      X1 X2 X3
    1  2  9  6
    2  4  6  7

1
Soyez prudent lors de l'utilisation -which, cela entraînera une erreur s'il n'y a pas de doublons, l'utilisation df[!(duplicated(df)), ]peut être plus sûre.
Objectif de Jason le

5

Avec sqldf:

# Example by Mehdi Nellen
a <- c(rep("A", 3), rep("B", 3), rep("C",2))
b <- c(1,1,2,4,1,1,2,2)
df <-data.frame(a,b)

Solution:

 library(sqldf)
    sqldf('SELECT DISTINCT * FROM df')

Production:

  a b
1 A 1
2 A 2
3 B 4
4 B 1
5 C 2

Cela entraîne la mise en place d'une base de données SQL entière. cran.r-project.org/web/packages/sqldf/index.html
qwr

Qu'entendez-vous par la configuration d'une base de données SQL entière? C'est l'un des principaux avantages: `` avec sqldf, l'utilisateur est libéré des opérations suivantes, qui sont toutes effectuées automatiquement: configuration de la base de données, écriture de l'instruction create table qui définit chaque table, importation et exportation vers et depuis la base de données ». Ce n'est pas une solution optimale, mais pratique pour ceux qui connaissent SQL.
mpalanco

3

Ou vous pouvez imbriquer les données des cols 4 et 5 dans une seule ligne avec tidyr:

library(tidyr)
df %>% nest(V4:V5)

# A tibble: 1 × 4
#                      V1    V2    V3             data
#                  <fctr> <int> <int>           <list>
#1 platform_external_dbus   202    16 <tibble [5 × 2]>

Les doublons de col 2 et 3 sont maintenant supprimés pour l'analyse statistique, mais vous avez conservé les données de col 4 et 5 dans un tibble et pouvez revenir à la base de données d'origine à tout moment avec unnest().


1

Supprimer les lignes en double d'un dataframe

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe
distinct(mydata)

Dans cet ensemble de données, il n'y a pas une seule ligne en double, il a donc renvoyé le même nombre de lignes que dans mydata.



Supprimer les lignes en double en fonction d'une seule variable

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe using carb variable
distinct(mydata,carb, .keep_all= TRUE)

La fonction .keep_all est utilisée pour conserver toutes les autres variables dans la trame de données de sortie.



Supprimer les lignes en double en fonction de plusieurs variables

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe using cyl and vs variables
distinct(mydata, cyl,vs, .keep_all= TRUE)

La fonction .keep_all est utilisée pour conserver toutes les autres variables dans la trame de données de sortie.

(à partir de: http://www.datasciencemadesimple.com/remove-duplicate-rows-r-using-dplyr-distinct-function/ )


0

Ce problème peut également être résolu en sélectionnant la première ligne de chaque groupe où le groupe est constitué des colonnes sur la base desquelles nous voulons sélectionner des valeurs uniques (dans l'exemple partagé, il ne s'agit que de la 1ère colonne).

En utilisant la base R:

subset(df, ave(V2, V1, FUN = seq_along) == 1)

#                      V1  V2 V3     V4 V5
#1 platform_external_dbus 202 16 google  1

Dans dplyr

library(dplyr)
df %>% group_by(V1) %>% slice(1L)

Ou en utilisant data.table

library(data.table)
setDT(df)[, .SD[1L], by = V1]

Si nous avons besoin de trouver des lignes uniques basées sur plusieurs colonnes, ajoutez simplement ces noms de colonnes dans une partie de regroupement pour chacune des réponses ci-dessus.

Les données

df <- structure(list(V1 = structure(c(1L, 1L, 1L, 1L, 1L), 
.Label = "platform_external_dbus", class = "factor"), 
V2 = c(202L, 202L, 202L, 202L, 202L), V3 = c(16L, 16L, 16L, 
16L, 16L), V4 = structure(c(1L, 4L, 3L, 5L, 2L), .Label = c("google", 
"hughsie", "localhost", "space-ghost.verbum", "users.sourceforge"
), class = "factor"), V5 = c(1L, 1L, 1L, 8L, 1L)), class = "data.frame", 
row.names = c(NA, -5L))

0

Voici un très simple, rapide dplyr/tidy solution:

Supprimez les lignes entièrement identiques:

library(dplyr)
iris %>% 
  distinct(.keep_all = TRUE)

Supprimez les lignes identiques uniquement dans certaines colonnes:

iris %>% 
  distinct(Sepal.Length, Sepal.Width, .keep_all = TRUE)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.