studio - Subconjunto de datos por múltiples condiciones lógicas de filas para eliminar
subset en r (8)
El !
debe estar alrededor de la declaración:
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
Me gustaría subconjuntar (filtrar) un marco de datos al especificar qué filas no ( !
) Mantener en el nuevo marco de datos. Aquí hay un marco de datos de muestra simplificado:
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
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 marco de datos:
v1 v2 v3 v4
a v d c
a v d d
c k d c
c r p g
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?
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
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.
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.
data <- data[-which(data[,1] %in% c("b","d","e")),]
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
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])
.