J'aimerais sous-définir un cadre de données pour inclure uniquement les lignes qui ont des combinaisons uniques de trois colonnes. Ma situation est similaire à celle présentée dans la question this , mais je voudrais également conserver les autres colonnes dans mes données. Voici mon exemple:
> df
v1 v2 v3 v4 v5
1 7 1 A 100 98
2 7 2 A 98 97
3 8 1 C NA 80
4 8 1 C 78 75
5 8 1 C 50 62
6 9 3 C 75 75
La sortie demandée serait quelque chose comme ceci, où je recherche des cas uniques basés uniquement sur v1, v2 et v3:
> df.new
v1 v2 v3 v4 v5
1 7 1 A 100 98
2 7 2 A 98 97
3 8 1 C NA 80
6 9 3 C 75 75
Si je pouvais récupérer les lignes non uniques, ce serait bien aussi:
> df.dupes
v1 v2 v3 v4 v5
3 8 1 C NA 80
4 8 1 C 78 75
5 8 1 C 50 62
J'ai vu une question connexe sur la façon de faire cela dans sql ( ici ), mais je ne peux pas obtenir cela dans R. Je suis sûr que c'est simple mais en jouant avec hasn unique () et subset () pas été fructueux. Merci d'avance.
Vous pouvez utiliser la fonction duplicated()
pour trouver les combinaisons uniques:
> df[!duplicated(df[1:3]),]
v1 v2 v3 v4 v5
1 7 1 A 100 98
2 7 2 A 98 97
3 8 1 C NA 80
6 9 3 C 75 75
Pour obtenir uniquement les doublons, vous pouvez le vérifier dans les deux sens:
> df[duplicated(df[1:3]) | duplicated(df[1:3], fromLast=TRUE),]
v1 v2 v3 v4 v5
3 8 1 C NA 80
4 8 1 C 78 75
5 8 1 C 50 62
En utilisant dplyr
, vous pourriez faire:
library(dplyr)
# distinct
df %>%
distinct(v1, v2, v3, .keep_all = T)
# non-distinct only
df %>%
group_by(v1, v2, v3) %>%
filter(n() > 1)
# exclude any non-distinct
df %>%
group_by(v1, v2, v3) %>%
filter(n() == 1)
Vous pouvez utiliser le package plyr
:
library(plyr)
ddply(df, c("v1","v2","v3"), head, 1)
# v1 v2 v3 v4 v5
# 1 7 1 A 100 98
# 2 7 2 A 98 97
# 3 8 1 C NA 80
# 4 9 3 C 75 75
ddply(df, c("v1","v2","v3"), function(x) if(nrow(x)>1) x else NULL)
# v1 v2 v3 v4 v5
# 1 8 1 C NA 80
# 2 8 1 C 78 75
# 3 8 1 C 50 62
oui mais utiliser plyr et ddply est très très lent si vous avez trop de données.
vous devriez essayer quelque chose de ce genre:
df[ cbind( which(duplicated(df[1:3])), which(duplicated(df[1:3], fromLast=TRUE))),]
ou::
from = which(duplicated(df[1:3])
to = which(duplicated(df[1:3], fromLast=TRUE))
df[cbind(from,to),]
shd être plus rapide pour la plupart.
testez-le et faites-nous savoir
il y a des erreurs, mais je suppose que vous pouvez les corriger tant que vous en avez l'idée.
essayez aussi unique et tout cela
Une manière non élégante mais fonctionnelle consiste à coller les entrées d'une ligne donnée et à trouver celles qui sont uniques (ou non uniques), quelque chose comme:
df.vector=apply(df,1,FUN=function(x) {paste(x,collapse="")})
df.table=table(df.vector)
puis récupérez les index des doublons avec quelque chose comme:
which(df.vector%in%names(which(df.table>1)))