web-dev-qa-db-fra.com

Extraire des lignes uniques d'une table de données dans R

Je migre des blocs de données et des matrices vers des tables de données, mais je n'ai pas trouvé de solution pour extraire les lignes uniques d'une table de données. Je suppose qu'il y a quelque chose qui me manque dans le [,J] notation, même si je n'ai pas encore trouvé de réponse dans les FAQ et vignettes d'introduction. Comment puis-je extraire les lignes uniques, sans reconvertir en trames de données?

Voici un exemple:

library(data.table)
set.seed(123)
a <- matrix(sample(2, 120, replace = TRUE), ncol = 3)
a <- as.data.frame(a)
b <- as.data.table(a)

# Confirm dimensionality
dim(a) # 40  3
dim(b) # 40  3

# Unique rows using all columns
dim(unique(a))  # 8 3
dim(unique(b))  # 34 3

# Unique rows using only a subset of columns
dim(unique(a[,c("V1","V2")]))   # 4 2
dim(unique(b[,list(V1,V2)]))    # 29 2

Question connexe: ce comportement résulte-t-il du non tri des données, comme avec la fonction Unix uniq?

27
Iterator

Avant data.table v1.9.8, le comportement par défaut de la méthode unique.data.table Était d'utiliser les clés afin de déterminer les colonnes par lesquelles les combinaisons uniques devaient être renvoyées. Si le key était NULL (par défaut), on récupérerait le jeu de données d'origine (comme dans la situation OP).

Depuis data.table 1.9.8+, la méthode unique.data.table Utilise toutes les colonnes par défaut, ce qui est cohérent avec unique.data.frame Dans la base R. Pour qu'elle utilise les colonnes clés, passez explicitement la fonction by = key(DT) dans unique (en remplaçant DT dans l'appel à la clé par le nom de data.table).

Par conséquent, l'ancien comportement serait quelque chose comme

library(data.table) v1.9.7-
set.seed(123)
a <- as.data.frame(matrix(sample(2, 120, replace = TRUE), ncol = 3))
b <- data.table(a, key = names(a))
## key(b)
## [1] "V1" "V2" "V3"
dim(unique(b)) 
## [1] 8 3

Alors que pour data.table v1.9.8 +, juste

b <- data.table(a) 
dim(unique(b)) 
## [1] 8 3
## or dim(unique(b, by = key(b)) # in case you have keys you want to use them

Ou sans copie

setDT(a)
dim(unique(a))
## [1] 8 3
28
user399470

Comme mentionné par Seth, le package data.table a évolué et propose désormais des fonctions optimisées pour cela.

Pour tous ceux qui ne veulent pas entrer dans la documentation, voici le moyen le plus rapide et le plus efficace en mémoire de faire ce que vous voulez:

uniqueN(a)

Et si vous souhaitez uniquement choisir un sous-ensemble de colonnes, vous pouvez utiliser l'argument "by":

uniqueN(a,by = c('V1','V2'))

EDIT: Comme mentionné dans les commentaires, cela ne donne que le nombre de lignes uniques. Pour obtenir les valeurs uniques, utilisez plutôt unique:

unique(a)

Et pour un sous-ensemble:

unique(a[c('V1',"V2")], by=c('V1','V2'))

7
Sacha