Jak usunąć wiele wartości z wektora?


125

Mam wektor taki jak: a = c(1:10)i muszę usunąć wiele wartości, takich jak:2, 3, 5

Jak usunąć te liczby ( NIE są to pozycje w wektorze) w wektorze?

w tej chwili zapętlam wektor i robię coś takiego:

a[!a=NUMBER_TO_REMOVE]

Ale myślę, że jest funkcja, która robi to automatycznie.

Odpowiedzi:


192

%in%Operator informuje, które elementy należą do numers do usunięcia:

> 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

Zauważ, że to po cichu usunie nieporównywalne elementy (takie jak NAlub Inf)również (podczas gdy zachowa zduplikowane wartości, ao ile nie są wymienione remove).

  • Jeśli amoże zawierać nieporównywalne, ale removenie będzie, możemy użyć match, mówiąc mu, aby zwracał 0po niedopasowania i nieporównywalne ( %in%jest to wygodny skrót do 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 = 0nie jest potrzebne, ponieważ elementy nieporównywalne i tak nie będą pasować, ale dołączyłbym to ze względu na czytelność.
    To jest przy okazji, co setdiffrobi wewnętrznie (ale bez uniquewyrzucania duplikatów, w aktórych nie ma remove).

  • Jeśli removezawiera nieporównywalne elementy, będziesz musiał sprawdzić je indywidualnie, np

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

    (To nie odróżnia NAod NaNale instrukcja R jakikolwiek ostrzega, że nie należy liczyć na o różnicę między nimi)

    Dla Inf/ -Infbędziesz musiał sprawdzić zarówno signiis.finite


1
setdiffjest lepsze, ponieważ robi wszystko w jednej operacji i odwołuje się do zmienionego wektora tylko raz.
Olexa

1
@Olexa: różnica zestawu nie zawsze jest tym samym, co usunięcie wszystkich wystąpień danego zbioru liczb z wektora: usunie to duplikaty, aktórych również nie ma remove. Jeśli to nie problem, możesz również użyć setdiff. setdiff, przy okazji, używa matchdo którego %in%jest skrót.
cbeleites niezadowolony z SX

97

Możesz użyć setdiff.

Dany

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

Następnie

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

1
bardzo przydatne, gdy ajest wynikiem innej funkcji, więc możesz robić rzeczy w jednej linii zamiast 3 i zmiennej tymczasowej
jf328

14
To da inne wyniki niż %in%rozwiązanie, jeśli wektor wejściowy zawiera duplikaty (w takim przypadku setdiffzwróci tylko unikalny zestaw , tj. Bez duplikatów)
talat

2
@docendodiscimus: fsetdiffof data.tablepackage ma allflagę (domyślnie F), która pozwala zachować duplikaty w wektorze wejściowym.
Juergen

9

Możesz to zrobić w następujący sposób:

> 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

Wkrótce

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

1
to, co nazywasz listą w twoim przykładzie, jest wektorem, prawda?
patrick

Tak, mam na myśli wektor. Dziękuję za komentarz.
ykpemre

Nie ma takiej potrzeby which. Zasadniczo jest to to samo, co odpowiedź @cbeleites.
David Arenburg

tak, jest podobnie, ale różni się w kilku punktach widzenia. whichzwraca indeksy wartości PRAWDA. Tak więc znak minus może być użyty do określenia „indeksów innych niż te indeksy”. whichJest też bardziej czytelny, ponieważ jest bliżej języka naturalnego.
ykpemre

4

zamiast

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

korzystając z pakietów purrri magrittrmożesz:

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

pozwala to na subsetjednorazowe użycie nazwy wektora. I możesz go używać w rurach :)


czy możesz wyjaśnić swoje ostatnie stwierdzenie dotyczące długości nazw zmiennych? Dlaczego tego nie lubisz? Dlaczego jest lepszy niż w drugą stronę? Lub usuń ten akapit, ponieważ nie jest związany z głównym problemem / pytaniem.
rodrigoap

2

Najpierw możemy zdefiniować nowy operator,

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

Wtedy to jak x nie jest usuwane

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

lub dlaczego zdecydować się na usunięcie, przejdź bezpośrednio

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

3
Pytanie konkretnie mówi, że 2, 3 i 5 nie są pozycjami w wektorze.
blakeoft

1

AKTUALIZACJA:

Wszystkie powyższe odpowiedzi nie będą działać dla powtarzających się wartości, odpowiedź @ BenBolker za pomocą duplicated()predykatu rozwiązuje ten problem:

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

Oryginalna odpowiedź: tutaj napiszę małą funkcję:

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

więc powiedzmy full_vector=c(1,2,3,4,1)i searched_vector=c(1,2,3).

exclude_val(full_vector,searched_vector)zwróci (4,1), jednak powyższe odpowiedzi zwrócą tylko (4).


1
o czym full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]?
Ben Bolker

@BenBolker ah Nie wiedziałem, że „zduplikowany” predykat: ((co teraz, mam usunąć swoją odpowiedź lub zmienić ją tak, aby wyświetlała tylko twoją?
Özgür

@BenBolker, twoje rozwiązanie jest złe; po prostu spróbuj: full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3);- to produkuje1, 1, 2 zamiast poprawnej odpowiedzi 1, 2.
fnl

Wystarczy dodać możliwe poprawne rozwiązanie dla powtarzających się wartości: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

To ustawia 13 w wektorze na nie liczbę (NAN), pokazuje fałszywe usuwanie (q [c (11,12,13)]). Jeśli spróbujesz tego, zobaczysz, że funkcja usuwania nie działa na numerze wektora. usuwasz cały wektor, ale może nie pojedynczy element.


1

Jest też subsetcoś, co czasami może się przydać:

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

> subset(a, !(a %in% bad))
[1]  9  7 10  6  8  1  4
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.