941 votes

Suppression des lignes avec toutes ou certaines NA (valeurs manquantes) dans le data.frame

Je voudrais supprimer les lignes dans ce cadre de données qui :

a) contiennent NA dans toutes les colonnes. Voici mon exemple de cadre de données.

             gene hsap mmul mmus rnor cfam
1 ENSG00000208234    0   NA   NA   NA   NA
2 ENSG00000199674    0   2    2    2    2
3 ENSG00000221622    0   NA   NA   NA   NA
4 ENSG00000207604    0   NA   NA   1    2
5 ENSG00000207431    0   NA   NA   NA   NA
6 ENSG00000221312    0   1    2    3    2

En gros, j'aimerais obtenir un cadre de données tel que le suivant.

             gene hsap mmul mmus rnor cfam
2 ENSG00000199674    0   2    2    2    2
6 ENSG00000221312    0   1    2    3    2

b) contiennent NA dans certaines colonnes seulement pour que je puisse également obtenir ce résultat :

             gene hsap mmul mmus rnor cfam
2 ENSG00000199674    0   2    2    2    2
4 ENSG00000207604    0   NA   NA   1    2
6 ENSG00000221312    0   1    2    3    2

1172voto

Joris Meys Points 38980

Vérifiez également complete.cases :

> final[complete.cases(final), ]
             gene hsap mmul mmus rnor cfam
2 ENSG00000199674    0    2    2    2    2
6 ENSG00000221312    0    1    2    3    2

na.omit est plus agréable pour supprimer tous les NA 's. complete.cases permet une sélection partielle en incluant seulement certaines colonnes du cadre de données :

> final[complete.cases(final[ , 5:6]),]
             gene hsap mmul mmus rnor cfam
2 ENSG00000199674    0    2    2    2    2
4 ENSG00000207604    0   NA   NA    1    2
6 ENSG00000221312    0    1    2    3    2

Votre solution ne peut pas fonctionner. Si vous insistez pour utiliser is.na alors vous devez faire quelque chose comme :

> final[rowSums(is.na(final[ , 5:6])) == 0, ]
             gene hsap mmul mmus rnor cfam
2 ENSG00000199674    0    2    2    2    2
4 ENSG00000207604    0   NA   NA    1    2
6 ENSG00000221312    0    1    2    3    2

mais en utilisant complete.cases est beaucoup plus claire et rapide.

11 votes

Quelle est la signification de la virgule de fin de phrase dans final[complete.cases(final),] ?

0 votes

Le site complete.cases(final) renvoie un booléen des lignes où il n'y a pas de NA comme (TRUE, FALSE, TRUE) . La virgule de fin indique toutes les colonnes. Ainsi, avant la virgule vous filtrez sur les lignes mais après la virgule vous colonne vous ne faites aucun filtrage et demandez tout.

0 votes

Merci pour cette solution, je n'étais pas au courant que l'on pouvait spécifier des colonnes avec la fonction complete.cases déclaration.

289voto

Roman Luštrik Points 19295

Essayez na.omit(your.data.frame) . Quant à la deuxième question, essayez de la poster comme une autre question (pour plus de clarté).

96voto

donshikin Points 476

Je préfère la méthode suivante pour vérifier si les lignes contiennent des NA :

row.has.na <- apply(final, 1, function(x){any(is.na(x))})

Cette fonction renvoie un vecteur logique avec des valeurs indiquant s'il y a un NA dans une ligne. Vous pouvez l'utiliser pour savoir combien de lignes vous devrez abandonner :

sum(row.has.na)

et finalement les laisser tomber

final.filtered <- final[!row.has.na,]

Pour filtrer les lignes contenant une certaine partie de NA, cela devient un peu plus délicat (par exemple, vous pouvez introduire 'final[,5:6]' dans 'apply'). En général, la solution de Joris Meys semble être plus élégante.

4 votes

C'est extrêmement lent. Beaucoup plus lent que, par exemple, la solution complete.cases() mentionnée plus haut. En tout cas, dans mon cas, sur des données xts.

3 votes

rowSum(!is.na(final)) semble mieux convenir que apply()

47voto

getting-there Points 417

Une autre option si vous voulez un plus grand contrôle sur la façon dont les rangées sont considérées comme invalides est

final <- final[!(is.na(final$rnor)) | !(is.na(rawdata$cfam)),]

En utilisant ce qui précède, ceci :

             gene hsap mmul mmus rnor cfam
1 ENSG00000208234    0   NA   NA   NA   2
2 ENSG00000199674    0   2    2    2    2
3 ENSG00000221622    0   NA   NA   2   NA
4 ENSG00000207604    0   NA   NA   1    2
5 ENSG00000207431    0   NA   NA   NA   NA
6 ENSG00000221312    0   1    2    3    2

Devient :

             gene hsap mmul mmus rnor cfam
1 ENSG00000208234    0   NA   NA   NA   2
2 ENSG00000199674    0   2    2    2    2
3 ENSG00000221622    0   NA   NA   2   NA
4 ENSG00000207604    0   NA   NA   1    2
6 ENSG00000221312    0   1    2    3    2

...où seule la ligne 5 est supprimée car c'est la seule ligne contenant des NA pour les deux rnor ET cfam . La logique booléenne peut ensuite être modifiée pour répondre à des besoins spécifiques.

6 votes

Mais comment utiliser ceci si vous voulez vérifier plusieurs colonnes, sans taper chacune d'entre elles, pouvez-vous utiliser une plage finale[,4:100] ?

19voto

Leo Points 21

Cela renverra les lignes qui ont au moins UNE valeur non-NA.

final[rowSums(is.na(final))<length(final),]

Cela renverra les lignes qui ont au moins DEUX valeurs non-NA.

final[rowSums(is.na(final))<(length(final)-1),]

0 votes

C'est parfait, j'étais en fait à la recherche d'une solution similaire qui pourrait nous permettre de ne garder que les lignes (indépendamment des colonnes) qui ont une ou plusieurs valeurs non-NA. Cependant, ce code ne fonctionne pas dans mon cas. Il conserve toutes les lignes, même celles qui ont toutes des NA.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X