¿Cómo eliminar múltiples valores de un vector?

125

Tengo un vector como: a = c(1:10)y necesito eliminar varios valores, como:2, 3, 5

¿Cómo eliminar esos números ( NO son las posiciones en el vector) en el vector?

en este momento, repito el vector y hago algo como:

a[!a=NUMBER_TO_REMOVE]

Pero creo que hay una función que lo hace automáticamente.

Dail
fuente

Respuestas:

192

El %in%operador le dice qué elementos están entre los números que se deben eliminar:

> a <- sample (1 : 10)
> remove <- c (2, 3, 5)
> a
 [1] 10  5  2  7  1  6  3  4  8  9
> a %in% remove
 [1] FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
> a [! a %in% remove]
 [1] 10  7  1  6  4  8  9

Tenga en cuenta que esto eliminará silenciosamente incomparables (cosas como NAo Inf)también (mientras mantendrá valores duplicados asiempre que no estén listados remove).

  • Si apuede contener incomparables, pero removeno lo hará, podemos usarlo match, diciéndole que regrese 0por no coincidencias e incomparables ( %in%es un atajo conveniente para match):

    > a <- c (a, NA, Inf)
    > a
     [1]  10   5   2   7   1   6   3   4   8   9  NA Inf
    > match (a, remove, nomatch = 0L, incomparables = 0L)
     [1] 0 3 1 0 0 0 2 0 0 0 0 0
    > a [match (a, remove, nomatch = 0L, incomparables = 0L) == 0L]
    [1]  10   7   1   6   4   8   9  NA Inf

    incomparables = 0no es necesario ya que los incomparables de todos modos no coincidirán, pero lo incluiría por razones de legibilidad.
    Esto es, por cierto, lo que setdiffhace internamente (pero sin uniquetirar los duplicados en los aque no están remove).

  • Si removecontiene incomparables, deberá verificarlos individualmente, p. Ej.

    if (any (is.na (remove))) 
      a <- a [! is.na (a)]

    (Esto no distingue NAde, NaNpero el manual R de todos modos advierte que no se debe confiar en tener una diferencia entre ellos)

    Para Inf/ -Inftendrás que marcar ambos signyis.finite

cbeleites descontentos con SX
fuente
1
setdiffes mejor, ya que hace todo en una operación y hace referencia al vector modificado solo una vez.
Olexa
1
@Olexa: la diferencia de conjunto no siempre es lo mismo que eliminar todas las ocurrencias de un conjunto de números dado de un vector: eliminará los duplicados aque no están removetambién. Si eso no es un problema, también puedes usarlo setdiff. setdiff, por cierto, usos matchpara los cuales %in%es un atajo.
Cbeleites descontento con SX
97

Puedes usar setdiff.

Dado

a <- sample(1:10)
remove <- c(2, 3, 5)

Luego

> a
 [1] 10  8  9  1  3  4  6  7  2  5
> setdiff(a, remove)
[1] 10  8  9  1  4  6  7
Brian Diggs
fuente
1
muy útil cuando aes el resultado de otra función para que pueda hacer cosas en una línea en lugar de 3 y una variable temporal
jf328
14
Esto producirá resultados diferentes que la %in%solución si el vector de entrada contiene duplicados (en cuyo caso setdiffsolo devolverá el conjunto único , es decir, sin duplicados)
talat
2
@docendodiscimus: fsetdiffdel data.tablepaquete tiene una allbandera (por defecto F) que permite mantener duplicados en el vector de entrada.
Juergen
9

Puedes hacerlo de la siguiente manera:

> x<-c(2, 4, 6, 9, 10) # the list
> y<-c(4, 9, 10) # values to be removed

> idx = which(x %in% y ) # Positions of the values of y in x
> idx
[1] 2 4 5
> x = x[-idx] # Remove those values using their position and "-" operator
> x
[1] 2 6

Dentro de poco

> x = x[ - which(x %in% y)]
ykpemre
fuente
1
lo que llamas una lista en tu ejemplo es un vector, ¿verdad?
patrick
Sí, me refiero al vector. Gracias por el comentario.
ykpemre
No hay necesidad whichaquí. Básicamente es lo mismo que @cbeleites answer.
David Arenburg
Sí, es similar, pero diferente en algunos puntos de vista. whichdevuelve índices de valores VERDADEROS. Por lo tanto, el signo menos se puede usar para decir "los índices que no sean estos índices". También whiches más legible ya que está más cerca del lenguaje natural.
ykpemre
4

en vez de

x <- x[! x %in% c(2,3,5)]

usando los paquetes purrry magrittrpuedes hacer:

your_vector %<>% discard(~ .x %in% c(2,3,5))

Esto permite subsetutilizar el nombre del vector solo una vez. Y puedes usarlo en tuberías :)

krishan404
fuente
¿puede explicar su última declaración sobre la longitud del nombre de las variables? ¿Por qué no te gusta eso? ¿Por qué es mejor que a la inversa? O bien, elimine ese párrafo ya que no está relacionado con el problema / pregunta principal.
rodrigoap
2

Primero podemos definir un nuevo operador,

"%ni%" = Negate( "%in%" )

Entonces, es como x no en eliminar

x <- 1:10
remove <- c(2,3,5)
x <- x[ x %ni% remove ]

o por qué ir para eliminar, ir directamente

x <- x[ x %ni% c(2,3,5)]
TheMI
fuente
3
La pregunta específicamente dice que 2, 3 y 5 no son posiciones en el vector.
blakeoft
1

ACTUALIZAR:

Todas las respuestas anteriores no funcionarán para los valores repetidos, la respuesta de @BenBolker usando un duplicated()predicado resuelve esto:

full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]

Respuesta original: aquí escribo una pequeña función para esto:

exclude_val<-function(full_vector,searched_vector){

      found=c()

      for(i in full_vector){  

        if(any(is.element(searched_vector,i))){
          searched_vector[(which(searched_vector==i))[1]]=NA
        }
        else{
          found=c(found,i)
        }
    }

    return(found)
}

entonces, digamos full_vector=c(1,2,3,4,1)y searched_vector=c(1,2,3).

exclude_val(full_vector,searched_vector)regresará (4,1), sin embargo, las respuestas anteriores solo devolverán (4).

Özgür
fuente
1
¿qué pasa full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]?
Ben Bolker
@BenBolker ah No conocía ese predicado "duplicado": ((¿ahora qué, debo eliminar mi respuesta o cambiarla para mostrar solo la suya?
Özgür
@BenBolker, su solución está mal; solo intente: full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3);eso produce en 1, 1, 2lugar de la respuesta correcta 1, 2.
fnl
Solo para agregar una posible solución correcta para valores repetidos:removeif <- function(from, where) { for (i in where) if (i %in% from) {from = from[-match(i, from)]}; from}
fnl
1
q <- c(1,1,2,2,3,3,3,4,4,5,5,7,7)
rm <- q[11]
remove(rm)
q
q[13] = NaN
q
q %in% 7

Esto establece el 13 en un vector como no un número (NAN), muestra una eliminación falsa (q [c (11,12,13)]) si intenta esto, verá que la función de eliminación no funciona en el número de vector. elimina todo el vector pero quizás no un solo elemento.

Mahendra
fuente
1

También hay algo subsetque puede ser útil a veces:

a <- sample(1:10)
bad <- c(2, 3, 5)

> subset(a, !(a %in% bad))
[1]  9  7 10  6  8  1  4
Karolis Koncevičius
fuente