web-dev-qa-db-fra.com

Filtrage des lignes dupliquées / non uniques dans le fichier data.table

J'ai une table data.table Avec environ 2,5 millions de lignes. Il y a deux colonnes. Je souhaite supprimer toutes les lignes dupliquées dans les deux colonnes. Auparavant, pour un data.frame, j'aurais fait ceci: df -> unique(df[,c('V1', 'V2')]) mais cela ne fonctionne pas avec data.table. J'ai essayé unique(df[,c(V1,V2), with=FALSE]) mais il semble que cela ne fonctionne toujours que sur la clé du fichier data.table et non sur la ligne entière.

Aucune suggestion?

À la vôtre, Davy

Exemple

>dt
      V1   V2
[1,]  A    B
[2,]  A    C
[3,]  A    D
[4,]  A    B
[5,]  B    A
[6,]  C    D
[7,]  C    D
[8,]  E    F
[9,]  G    G
[10,] A    B

dans la table des données ci-dessus où V2 est la clé de la table, seules les lignes 4, 7 et 10 seraient supprimées.

> dput(dt)
structure(list(V1 = c("B", "A", "A", "A", "A", "A", "C", "C", 
"E", "G"), V2 = c("A", "B", "B", "B", "C", "D", "D", "D", "F", 
"G")), .Names = c("V1", "V2"), row.names = c(NA, -10L), class = c("data.table", 
"data.frame"), .internal.selfref = <pointer: 0x7fb4c4804578>, sorted = "V2")
68
Davy Kavanagh

Antérieur v1.9.8

De ?unique.data.table, il est clair que l'appel de unique sur une table de données ne fonctionne que sur la clé. Cela signifie que vous devez réinitialiser la clé sur toutes les colonnes avant d'appeler unique.

library(data.table)
dt <- data.table(
  V1=LETTERS[c(1,1,1,1,2,3,3,5,7,1)],
  V2=LETTERS[c(2,3,4,2,1,4,4,6,7,2)]
)

Appeler unique avec une colonne comme clé:

setkey(dt, "V2")
unique(dt)
     V1 V2
[1,]  B  A
[2,]  A  B
[3,]  A  C
[4,]  A  D
[5,]  E  F
[6,]  G  G

Pour v1.9.8 +

De ?unique.data.table Par défaut, toutes les colonnes sont utilisées (ce qui est compatible avec ?unique.data.frame)

unique(dt)
   V1 V2
1:  A  B
2:  A  C
3:  A  D
4:  B  A
5:  C  D
6:  E  F
7:  G  G

Ou en utilisant l'argument by pour obtenir des combinaisons uniques de colonnes spécifiques (comme auparavant, les clés étaient utilisées)

unique(dt, by = "V2")
   V1 V2
1:  A  B
2:  A  C
3:  A  D
4:  B  A
5:  E  F
6:  G  G
81
Andrie

Avec votre exemple data.table ...

> dt<-data.table(V1 = c("B", "A", "A", "A", "A", "A", "C", "C", "E", "G"), V2 = c("A", "B", "B", "B", "C", "D", "D", "D", "F", "G"))
> setkey(dt,V2)

Considérons les tests suivants:

> haskey(dt) # obviously dt has a key, since we just set it
[1] TRUE

> haskey(dt[,list(V1,V2)]) # ... but this is treated like a "new" table, and does not have a key
[1] FALSE

> haskey(dt[,.SD]) # note that this still has a key
[1] TRUE

Donc, vous pouvez lister les colonnes de la table et ensuite prendre la unique() de celle-ci, sans avoir besoin de définir la clé sur toutes les colonnes ni de la supprimer (en la définissant sur NULL) requis par la solution de @Andrie (et édité par @MatthewDowle). Les solutions proposées par @Pop et @Rahul n'ont pas fonctionné pour moi.

Voir Essai 3 ci-dessous, qui est très similaire à votre essai initial. Votre exemple n'était pas clair, alors je ne sais pas pourquoi cela n'a pas fonctionné. En outre, vous avez posté la question il y a quelques mois. Peut-être que data.table A été mis à jour?

> unique(dt) # Try 1: wrong answer (missing V1=C and V2=D)
   V1 V2
1:  B  A
2:  A  B
3:  A  C
4:  A  D
5:  E  F
6:  G  G

> dt[!duplicated(dt)] # Try 2: wrong answer (missing V1=C and V2=D)
   V1 V2
1:  B  A
2:  A  B
3:  A  C
4:  A  D
5:  E  F
6:  G  G

> unique(dt[,list(V1,V2)]) # Try 3: correct answer; does not require modifying key
   V1 V2
1:  B  A
2:  A  B
3:  A  C
4:  A  D
5:  C  D
6:  E  F
7:  G  G

> setkey(dt,NULL)
> unique(dt) # Try 4: correct answer; requires key to be removed
   V1 V2
1:  B  A
2:  A  B
3:  A  C
4:  A  D
5:  C  D
6:  E  F
7:  G  G
7
dnlbrky

unique(df) fonctionne sur votre exemple.

1
Pop

Cela devrait fonctionner pour vous

dt <- unique(dt, by = c('V1, 'V2'))
0
Magma