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.