Come eliminare più valori da un vettore?


125

Ho un vettore come: a = c(1:10)e ho bisogno di rimuovere più valori, come:2, 3, 5

Come eliminare quei numeri ( NON sono le posizioni nel vettore) nel vettore?

al momento giro il vettore e faccio qualcosa del tipo:

a[!a=NUMBER_TO_REMOVE]

Ma penso che ci sia una funzione che lo fa automaticamente.

Risposte:


192

L' %in%operatore ti dice quali elementi sono tra i numeri da rimuovere:

> 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

Nota che questo rimuoverà silenziosamente incomparabili (cose simili NAo Inf)pure (mentre manterrà valori duplicati afinché non sono elencati in remove).

  • Se apuò contenere incomparabili, ma removenon lo è, possiamo usarlo match, dicendogli di tornare 0per non corrispondenze e incomparabili ( %in%è un collegamento conventiente per 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 = 0non è necessario in quanto gli incomparabili non corrisponderanno comunque, ma lo includerei per motivi di leggibilità.
    Questo è, tra l'altro, ciò che setdifffa internamente (ma senza il uniquebuttare via i duplicati in acui non ci sono remove).

  • Se removecontiene incomparabili, dovrai verificarli singolarmente, ad es

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

    (Questo non distingue NAdal NaNma il manuale R avverte comunque che non si deve fare affidamento su avente una differenza tra loro)

    Per Inf/ -Infdovrai controllare sia signeis.finite


1
setdiffè migliore, poiché fa tutto in un'unica operazione e fa riferimento al vettore modificato una sola volta.
Olexa,

1
@Olexa: la differenza di set non è sempre la stessa della rimozione di tutte le occorrenze di un determinato set di numeri da un vettore: rimuoverà anche i duplicati ache non sono presenti remove. Se questo non è un problema, puoi anche usare setdiff. setdiff, tra l'altro, usa matchper il quale %in%è una scorciatoia.
cbeleites insoddisfatto di SX il

97

È possibile utilizzare setdiff.

Dato

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

Poi

> a
 [1] 10  8  9  1  3  4  6  7  2  5
> setdiff(a, remove)
[1] 10  8  9  1  4  6  7

1
molto utile quando aè il risultato di un'altra funzione in modo da poter fare le cose in una riga anziché 3 e una variabile temp
jf328

14
Questo produrrà risultati diversi rispetto alla %in%soluzione se il vettore di input contiene duplicati (nel qual caso setdiffrestituirà solo il set univoco , cioè senza duplicati)
talat

2
@docendodiscimus: fsetdiffdel data.tablepacchetto ha un allflag (F predefinito) che consente di mantenere i duplicati nel vettore di input.
Juergen,

9

Puoi farlo come segue:

> 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

In breve

> x = x[ - which(x %in% y)]

1
quello che stai chiamando un elenco nel tuo esempio è un vettore, giusto?
patrick,

Sì, intendo il vettore. Grazie per il commento.
ykpemre,

Non è necessario whichqui. È praticamente la stessa della risposta di @cbeleites.
David Arenburg,

sì, è simile, ma diverso in alcuni punti di vista. whichrestituisce indici di TRUE valori. Quindi il segno meno può essere usato per dire "gli indici diversi da questi indici". Inoltre whichè più leggibile poiché è più vicino al linguaggio naturale.
ykpemre,

4

invece di

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

usando i pacchetti purrre magrittrpuoi fare:

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

questo consente di subsetusare il nome del vettore solo una volta. E puoi usarlo in tubi :)


puoi spiegare la tua ultima affermazione sulla lunghezza del nome delle variabili? Perché non ti piace? Perché è meglio dell'altro modo? In alternativa, rimuovere quel paragrafo poiché non è correlato al problema / domanda principale.
Rodrigoap,

2

Per prima cosa possiamo definire un nuovo operatore,

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

Quindi, è come x non in rimozione

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

o perché andare per rimuovere, vai direttamente

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

3
La domanda dice specificamente che 2, 3 e 5 non sono posizioni nel vettore.
Blakeoft,

1

AGGIORNARE:

Tutte le risposte sopra non funzioneranno per i valori ripetuti, la risposta di @ BenBolker usando duplicated()predicato risolve questo:

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

Risposta originale: qui scrivo una piccola funzione per questo:

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)
}

quindi, diciamo full_vector=c(1,2,3,4,1)e searched_vector=c(1,2,3).

exclude_val(full_vector,searched_vector)restituirà (4,1), tuttavia le risposte sopra restituiranno solo (4).


1
che dire full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]?
Ben Bolker,

@BenBolker ah non sapevo che predicato "duplicato": ((ora cosa devo eliminare la mia risposta o cambiarla per mostrare solo la tua?
Özgür

@BenBolker, la tua soluzione è sbagliata; basta provare: full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3);- che produce 1, 1, 2invece della risposta corretta 1, 2.
fnl,

Solo per aggiungere una possibile, corretta soluzione per valori ripetuti: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

Questo imposta il 13 in un vettore a non un numero (NAN) mostra false remove (q [c (11,12,13)]) se provi questo vedrai che la funzione di rimozione non funziona sul numero di vettore. rimuovi l'intero vettore ma forse non un singolo elemento.


1

C'è anche quello subsetche potrebbe essere utile a volte:

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

> subset(a, !(a %in% bad))
[1]  9  7 10  6  8  1  4
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.