Comment puis-je sous-définir le dataframe ci-dessous pour afficher uniquement les lignes où les colonnes AAA:CCC
ont toutes la même valeur et conserver le champ IndID
?
Dat <- data.frame(IndID = LETTERS[seq(1,10)],
AAA = c(1,5,3,2,3,1,5,4,6,2),
BBB = c(1,8,5,2,5,4,8,4,4,5),
CCC = c(1,5,3,2,3,5,5,4,6,5))
> Dat
IndID AAA BBB CCC
1 A 1 1 1
2 B 5 8 5
3 C 3 5 3
4 D 2 2 2
5 E 3 5 3
6 F 1 4 5
7 G 5 8 5
8 H 4 4 4
9 I 6 4 6
10 J 2 5 5
Je voudrais retourner le résultat suivant.
Result <- data.frame(IndID = c("A", "D", "H"),
AAA = c(1,2,4),
BBB = c(1,2,4),
CCC = c(1,2,4))
> Result
IndID AAA BBB CCC
1 A 1 1 1
2 D 2 2 2
3 H 4 4 4
J'ai trouvé un certain nombre d'articles connexes, notamment Rechercher les lignes dupliquées (basées sur 2 colonnes) dans le bloc de données dans R et Rechercher les doublons éléments avec dplyr, entre autres, mais n'ont pas pu reproduire le résultat souhaité avec trois colonnes. Par exemple, lors de la fermeture, le code ci-dessous montre toutes les distinct
lignes, mais avec le résultat indésirable de l'inclusion de lignes, seules deux des valeurs sont égales.
Dat %>% distinct(AAA, BBB, CCC)
Je soupçonne que la solution implique filter
mais je ne sais pas comment obtenir le résultat souhaité à partir de l'exemple mentionné ci-dessus. Une solution dplyr
est préférable.
Ajout Je me demande également si cela pourrait s'appliquer à plusieurs facteurs. Par exemple, avec les données ci-dessous, qui contiennent un IndID
et trois dates stockées en tant que facteurs, un résultat similaire peut-il être produit en autorisant des facteurs ou en changeant les facteurs en valeurs numériques?
Dat <- structure(list(GenIndID = structure(c(1L, 2L, 6L, 7L, 3L, 4L,
8L, 5L), .Label = c("BHS_601", "BHS_603", "BHS_604", "BHS_605",
"BHS_631", "BHS_635", "BHS_636", "BHS_637"), class = "factor"),
CptrDate = structure(c(1L, 2L, 3L, 3L, 2L, 2L, 3L, 4L), .Label = c("2016-02-01",
"2016-02-02", "2016-02-04", "2016-12-11"), class = "factor"),
DtLastAlive = structure(c(2L, 2L, 1L, 1L, 2L, 2L, 1L, 3L), .Label = c("2016-02-04",
"2017-07-13", "2017-08-27"), class = "factor"), DtFnlFate = structure(c(2L,
2L, 1L, 1L, 2L, 2L, 1L, 3L), .Label = c("2016-02-04", "2017-07-13",
"2017-08-27"), class = "factor")), .Names = c("GenIndID",
"CptrDate", "DtLastAlive", "DtFnlFate"), row.names = c(82L, 83L,
224L, 225L, 84L, 85L, 226L, 360L), class = "data.frame")
> Dat
GenIndID CptrDate DtLastAlive DtFnlFate
82 BHS_601 2016-02-01 2017-07-13 2017-07-13
83 BHS_603 2016-02-02 2017-07-13 2017-07-13
224 BHS_635 2016-02-04 2016-02-04 2016-02-04
225 BHS_636 2016-02-04 2016-02-04 2016-02-04
84 BHS_604 2016-02-02 2017-07-13 2017-07-13
85 BHS_605 2016-02-02 2017-07-13 2017-07-13
226 BHS_637 2016-02-04 2016-02-04 2016-02-04
360 BHS_631 2016-12-11 2017-08-27 2017-08-27
Le résultat souhaité étant
> Dat[c(3, 4, 7),]
GenIndID CptrDate DtLastAlive DtFnlFate
224 BHS_635 2016-02-04 2016-02-04 2016-02-04
225 BHS_636 2016-02-04 2016-02-04 2016-02-04
226 BHS_637 2016-02-04 2016-02-04 2016-02-04
4 réponses
Voici une autre solution avec apply
et all
:
Dat[apply(Dat[,-1], 1, function(x) all(x==x[1])),]
Ou avec filter_at
de dplyr
:
library(dplyr)
Dat %>%
filter_at(vars(AAA:CCC), all_vars(. == .data$AAA))
Résultat:
IndID AAA BBB CCC
1 A 1 1 1
4 D 2 2 2
8 H 4 4 4
Modifier:
En réponse à l'exemple supplémentaire d'OP, l'exemple apply
fonctionnerait quel que soit le type de variable. Ainsi, ce qui suit fonctionnerait pour le nouvel exemple:
Dat[apply(Dat[,-1], 1, function(x) all(x==x[1])),]
Résultat:
GenIndID CptrDate DtLastAlive DtFnlFate
224 BHS_635 2016-02-04 2016-02-04 2016-02-04
225 BHS_636 2016-02-04 2016-02-04 2016-02-04
226 BHS_637 2016-02-04 2016-02-04 2016-02-04
Pour filter_at
, cependant, si les colonnes à comparer sont celles de factor
, il faudrait d'abord convertir en character
:
Dat %>%
filter_at(vars(-1), all_vars(as.character(.) == .data$CptrDate))
Notez que vous devez seulement convertir .
en caractère, mais pas .data$CptrDate
car les facteurs peuvent être comparés avec des caractères, mais pas avec un autre facteur avec des niveaux différents.
Une alternative serait:
Dat %>%
mutate_at(vars(-1), as.character) %>%
filter_at(vars(-1), all_vars(. == .data$CptrDate))
Résultat:
GenIndID CptrDate DtLastAlive DtFnlFate
1 BHS_635 2016-02-04 2016-02-04 2016-02-04
2 BHS_636 2016-02-04 2016-02-04 2016-02-04
3 BHS_637 2016-02-04 2016-02-04 2016-02-04
Si vous n'avez besoin que d'un sous-ensemble de 3 colonnes, vous pouvez utiliser l'opérateur DF [,].
# DF[where rows have a value, select columns]
# [where rows where AAA==BBB==CCC, select all columns with ""]
temp <- Dat[Dat$AAA == Dat$BBB & Dat$BBB == Dat$CCC,]
Vous pouvez avoir une solution vectorisée:
Dat[do.call(function(...) pmax(...) - pmin(...), Dat[, -1]) == 0,]
# IndID AAA BBB CCC
#1 A 1 1 1
#4 D 2 2 2
#8 H 4 4 4
Vous pouvez utiliser une combinaison de range()
et diff()
.
Dat[apply(Dat[ ,-1], 1, function(x) diff(range(x)))==0, ]
# IndID AAA BBB CCC
# 1 A 1 1 1
# 4 D 2 2 2
# 8 H 4 4 4
range()
vous donne le minimum et le maximum d'un vecteur. diff()
vous donne la différence entre les valeurs d'un vecteur. Si la différence entre min-value
et max-value
est nulle, vous savez que toutes les valeurs sont égales. Si nous appliquons cette ligne par ligne en utilisant apply
, nous obtenons un vecteur TRUE
/ FALSE
que nous pouvons utiliser pour indexer Dat
.
Petits exemples pour illustrer la logique:
test <- c(1, 5, 3)
minmax <- range(test) # gives c(1,5)
diff(minmax) # gives 4
diff(range(c(1, 1, 1))) # gives 0
Si nous vérifions pour chaque ligne, si diff(range(your_row))
est égal à zéro ou non, nous pouvons utiliser la sortie de celle-ci pour indexer Dat
, comme nous l'avons fait ci-dessus.
Questions connexes
De nouvelles questions
r
R est un langage de programmation et un environnement logiciel libres et open source pour le calcul statistique, la bioinformatique, la visualisation et le calcul général. Veuillez fournir des exemples minimaux et reproductibles ainsi que le résultat souhaité. Utilisez dput () pour les données et spécifiez tous les packages non basiques avec des appels à library (). N'incorporez pas d'images pour les données ou le code, utilisez plutôt des blocs de code en retrait. Pour les questions relatives aux statistiques, utilisez https://stats.stackexchange.com.