web-dev-qa-db-fra.com

Sous-ensemble de données par plusieurs conditions logiques de lignes à supprimer

Je voudrais sous-filtre (filtre) un cadre de données en spécifiant quelles lignes not (!) à conserver dans le nouveau cadre de données. Voici un exemple simplifié de cadre de données:

data
v1 v2 v3 v4
a  v  d  c
a  v  d  d
b  n  p  g
b  d  d  h    
c  k  d  c    
c  r  p  g
d  v  d  x
d  v  d  c
e  v  d  b
e  v  d  c

Par exemple, si une ligne de la colonne v1 comporte un "b", un "d" ou un "e", je souhaite supprimer cette ligne d'observations en produisant le cadre de données suivant:

v1 v2 v3 v4
a  v  d  c
a  v  d  d
c  k  d  c    
c  r  p  g

J'ai réussi à sous-définir en fonction d'une condition à la fois. Par exemple, ici je supprime les lignes où v1 contient un "b":

sub.data <- data[data[ , 1] != "b", ]

Cependant, j'ai beaucoup, beaucoup de ces conditions, donc le faire une à la fois n'est pas souhaitable. Je n'ai pas réussi avec ce qui suit:

sub.data <- data[data[ , 1] != c("b", "d", "e")

ou

sub.data <- subset(data, data[ , 1] != c("b", "d", "e"))

J'ai aussi essayé d'autres choses, comme !%in%, mais cela ne semble pas exister. Des idées?

37
Jota

Le ! devrait être à l'extérieur de la déclaration:

data[!(data$v1 %in% c("b", "d", "e")), ]

  v1 v2 v3 v4
1  a  v  d  c
2  a  v  d  d
5  c  k  d  c
6  c  r  p  g
39
Andrie

Essaye ça

subset(data, !(v1 %in% c("b","d","e")))
46
chl

Vous pouvez également accomplir cela en séparant les éléments en instructions logiques distinctes en incluant & pour séparer les déclarations.

subset(my.df, my.df$v1 != "b" & my.df$v1 != "d" & my.df$v1 != "e")

Ce n'est pas élégant et prend plus de code mais pourrait être plus lisible par les nouveaux utilisateurs de R. Comme indiqué dans un commentaire ci-dessus, subset est une fonction de "commodité" qui est mieux utilisée en mode interactif.

10
N Brouwer
data <- data[-which(data[,1] %in% c("b","d","e")),]
5
paul c

Cette réponse est plus destinée à expliquer pourquoi, pas comment. L'opérateur '==' Dans R est vectorisé de la même manière que l'opérateur '+'. Il fait correspondre les éléments de ce qui se trouve du côté gauche aux éléments de ce qui se trouve du côté droit, élément par élément. Par exemple:

> 1:3 == 1:3
[1] TRUE TRUE TRUE

Ici, le premier test est 1==1 Qui est VRAI, le deuxième 2==2 Et le troisième 3==3. Notez que cela retourne FALSE dans les premier et deuxième éléments parce que l'ordre est incorrect:

> 3:1 == 1:3
[1] FALSE  TRUE FALSE

Maintenant, si un objet est plus petit que l'autre, le plus petit objet est répété autant que nécessaire pour correspondre au plus grand objet. Si la taille de l'objet plus grand n'est pas une multiplication de la taille de l'objet plus petit, vous recevez un avertissement indiquant que tous les éléments ne sont pas répétés. Par exemple:

>  1:2 == 1:3
[1]  TRUE  TRUE FALSE
Warning message:
In 1:2 == 1:3 :
  longer object length is not a multiple of shorter object length

Ici, le premier match est 1==1, Puis 2==2 Et enfin 1==3 (FALSE) car le côté gauche est plus petit. Si l'un des côtés n'est qu'un élément, cela se répète:

> 1:3 == 1
[1]  TRUE FALSE FALSE

L'opérateur correct pour tester si un élément est dans un vecteur est bien '%in%' Qui n'est vectorisé que sur l'élément de gauche (pour chaque élément du vecteur de gauche, il est testé s'il fait partie d'un objet de l'élément de droite. ).

Vous pouvez également utiliser '&' Pour combiner deux instructions logiques. '&' Prend deux éléments et vérifie élément par élément si les deux sont VRAI:

> 1:3 == 1 & 1:3 != 2
[1]  TRUE FALSE FALSE
4
Sacha Epskamp
my.df <- read.table(textConnection("
v1 v2 v3 v4
a  v  d  c
a  v  d  d
b  n  p  g
b  d  d  h    
c  k  d  c    
c  r  p  g
d  v  d  x
d  v  d  c
e  v  d  b
e  v  d  c"), header = TRUE)

my.df[which(my.df$v1 != "b" & my.df$v1 != "d" & my.df$v1 != "e" ), ]

  v1 v2 v3 v4
1  a  v  d  c
2  a  v  d  d
5  c  k  d  c
6  c  r  p  g
3
Roman Luštrik

Et aussi

library(dplyr)
data %>% filter(!v1 %in% c("b", "d", "e"))

ou

data %>% filter(v1 != "b" & v1 != "d" & v1 != "e")

ou

data %>% filter(v1 != "b", v1 != "d", v1 != "e")

Depuis le & opérateur est impliqué par la virgule.

1
Joe
sub.data<-data[ data[,1] != "b"  & data[,1] != "d" & data[,1] != "e" , ]

Plus grand mais simple à comprendre (je suppose) et peut être utilisé avec plusieurs colonnes, même avec !is.na( data[,1]).

1
Hernan