Subconjunto de datos por múltiples condiciones lógicas de filas para eliminar

Me gustaría subconjuntar (filtrar) un dataframe al especificar qué filas no ( ! ) Mantener en el nuevo dataframe. Aquí hay un dataframe de muestra simplificado:

 data v1 v2 v3 v4 avdc avdd bnpg bddhckdccrpg dvdx dvdc evdb evdc 

Por ejemplo, si una fila de la columna v1 tiene una “b”, “d” o “e”, quiero deshacerme de esa fila de observaciones, produciendo el siguiente dataframe:

 v1 v2 v3 v4 avdc avdd ckdccrpg 

He tenido éxito en el subconjunto basado en una condición a la vez. Por ejemplo, aquí elimino las filas donde v1 contiene una “b”:

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

Sin embargo, tengo muchas, muchas de esas condiciones, por lo que hacerlo de a una por vez no es deseable. No he tenido éxito con lo siguiente:

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

o

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

También probé otras cosas, como !%in% , pero eso no parece existir. ¿Algunas ideas?

El ! debe estar alrededor de la statement:

 data[!(data$v1 %in% c("b", "d", "e")), ] v1 v2 v3 v4 1 avdc 2 avdd 5 ckdc 6 crpg 

Prueba esto

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

También puede lograr esto dividiendo las cosas en declaraciones lógicas separadas al incluir & para separar las declaraciones.

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

Esto no es elegante y requiere más código, pero podría ser más legible para los usuarios R más nuevos. Como se señaló en un comentario anterior, el subset es una función de “conveniencia” que se utiliza mejor cuando se trabaja de forma interactiva.

 data <- data[-which(data[,1] %in% c("b","d","e")),] 

Esta respuesta está más destinada a explicar por qué, no cómo. El operador '==' en R se vectoriza de la misma manera que el operador '+' . Combina los elementos de lo que sea del lado izquierdo con los elementos de lo que esté en el lado derecho, por elemento. Por ejemplo:

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

Aquí la primera prueba es 1==1 que es VERDADERO, el segundo 2==2 y el tercero 3==3 . Observe que esto devuelve un FALSE en el primer y segundo elemento porque el orden es incorrecto:

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

Ahora bien, si un objeto es más pequeño que el otro objeto, entonces el objeto más pequeño se repite tanto como se necesita para hacer coincidir el objeto más grande. Si el tamaño del objeto más grande no es una multiplicación del tamaño del objeto más pequeño, recibirá una advertencia de que no todos los elementos se repiten. Por ejemplo:

 > 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 

Aquí el primer partido es 1==1 , luego 2==2 , y finalmente 1==3 (FALSO) porque el lado izquierdo es más pequeño. Si uno de los lados es solo un elemento, entonces eso se repite:

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

El operador correcto para probar si un elemento está en un vector es de hecho '%in%' que se vectoriza solo al elemento izquierdo (para cada elemento en el vector izquierdo se prueba si es parte de cualquier objeto en el elemento correcto) .

Alternativamente, puede usar '&' para combinar dos declaraciones lógicas. '&' toma dos elementos y comprueba elemento si ambos son VERDADEROS:

 > 1:3 == 1 & 1:3 != 2 [1] TRUE FALSE FALSE 
 my.df <- read.table(textConnection(" v1 v2 v3 v4 avdc avdd bnpg bddhckdccrpg dvdx dvdc evdb evdc"), header = TRUE) my.df[which(my.df$v1 != "b" & my.df$v1 != "d" & my.df$v1 != "e" ), ] v1 v2 v3 v4 1 avdc 2 avdd 5 ckdc 6 crpg 

Y también

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

o

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

o

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

Dado que el operador & está implícito en la coma.

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

Más grande pero fácil de entender (supongo) y puede usarse con múltiples columnas, incluso con !is.na( data[,1]) .