Bir vektörden birden çok değer nasıl silinir?


125

Şunun gibi bir vektörüm var a = c(1:10)ve birden çok değeri kaldırmam gerekiyor, örneğin:2, 3, 5

Vektördeki bu sayılar ( vektördeki konumlar DEĞİLDİR) nasıl silinir ?

şu anda vektörü döngüye alıyorum ve şöyle bir şey yapıyorum:

a[!a=NUMBER_TO_REMOVE]

Ama bunu otomatik olarak yapan bir işlev olduğunu düşünüyorum.

Yanıtlar:


192

%in%Operatör kaldır etmek numers arasındadır hangi unsurlar söyler:

> 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

Bunun, benzersiz olmayanları ( NAveya benzeri şeyler) sessizce kaldıracağına dikkat edin ( listede olmadıkları sürece Inf)yinelenen değerleri tutacaktır ).aremove

  • Karşılaştırılamazlar aiçerebilir, ancak içermeyecekse, eşleşmeyenler ve karşılaştırılamazlar için geri dönmesini söyleyerek removekullanabiliriz ( uygun bir kısayol ):match0%in%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 = 0değil gerekli neyse uymayacak incomparables olarak, ama okunabilirlik uğruna dahil olur.
    Bu Btw olduğunu. Ne setdiffiçten yapar (ancak olmadan uniqueçiftleri atmak için ahangi değildir remove).

  • Eğer removeincomparables içeren tek tek onlar için, örneğin kontrol etmek gerekir

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

    (Bu farklı değildir NA, NaNancak R kılavuzu yine de birinin aralarında bir fark olmasına güvenmemesi gerektiği konusunda uyarır)

    İçin Inf/ -InfHem kontrol gerekecek signveis.finite


1
setdiffher şeyi tek bir işlemde yaptığı ve değiştirilmiş vektöre yalnızca bir kez başvurduğu için daha iyidir.
Olexa

1
@Olexa: küme farkı, belirli bir sayı kümesinin tüm oluşumlarını bir vektörden kaldırmakla her zaman aynı değildir: içinde aolmayan kopyaları da kaldıracaktır remove. Bu bir sorun değilse, bunu da kullanabilirsiniz setdiff. setdiff, btw, kısayol matcholan kullanır %in%.
2019

97

Kullanabilirsiniz setdiff.

verilmiş

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

Sonra

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

1
abaşka bir işlevin sonucu olduğunda çok kullanışlıdır , bu nedenle işleri 3 ve geçici değişken yerine tek satırda yapabilirsiniz
jf328

14
Bu %in%, giriş vektörü kopyalar içeriyorsa çözümden farklı sonuçlar üretecektir (bu durumda setdiffyalnızca benzersiz kümeyi döndürür , yani kopyalar olmadan)
talat

2
@docendodiscimus: fsetdiffait data.tablepaketi vardır allbayrağı (F varsayılan) giriş vektörü çiftleri saklamanızı sağlar.
Juergen

9

Bunu şu şekilde yapabilirsiniz:

> 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

kısaca

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

1
Örneğinizde bir liste olarak adlandırdığınız şey bir vektör, değil mi?
patrick

Evet, vektörü kastediyorum. Yorum için teşekkürler.
ykpemre

Burada gerek whichyok. Temelde @cbeleites cevabı ile aynı.
David Arenburg

evet benzer, ancak birkaç açıdan farklı. whichDOĞRU değerlerin dizinlerini döndürür. Yani eksi işareti "bu indeksler dışındaki indeksler" demek için kullanılabilir. Ayrıca whichdoğal dile daha yakın olduğu için daha okunaklı.
ykpemre

4

onun yerine

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

paketleri kullanarak purrrve magrittrbunu yapabilirsiniz:

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

bu subset, vektör adının yalnızca bir kez kullanılmasına izin verir . Ve borularda kullanabilirsiniz :)


değişken isim uzunluğu hakkındaki son ifadenizi açıklar mısınız? Neden bundan hoşlanmıyorsun? Neden diğerinden daha iyidir? Veya, ana konu / soru ile ilgili olmadığı için bu paragrafı kaldırın.
rodrigoap

2

İlk önce yeni bir operatör tanımlayabiliriz,

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

Sonra, x'in kaldırılmaması gibi

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

veya neden kaldırılmalı, doğrudan git

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

3
Soru özellikle 2, 3 ve 5'in vektördeki konumlar olmadığını söylüyor.
blakeoft

1

GÜNCELLEME:

Yukarıdaki cevapların tümü tekrarlanan değerler için işe yaramayacaktır, @ BenBolker'in duplicated()yüklemi kullanan cevabı bunu çözer:

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

Orijinal Cevap: Burada bunun için küçük bir fonksiyon yazıyorum:

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

öyleyse, diyelim full_vector=c(1,2,3,4,1)ve searched_vector=c(1,2,3).

exclude_val(full_vector,searched_vector)(4,1) döndürür, ancak yukarıdaki yanıtlar yalnızca dönecektir (4).


1
peki ya full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]?
Ben Bolker

@BenBolker ah O "çoğaltılamaz" yüklemi bilmiyordum: ((cevabımı sileceksiniz şimdi ne, ya da bunun yerine sadece sen göster olarak değiştirin?
Özgür

@BenBolker, çözümünüz yanlış; sadece deneyin: full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3);- bu 1, 1, 2, doğru cevap yerine üretir 1, 2.
fnl

Tekrarlanan değerler için olası, doğru bir çözüm eklemek için: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

Bu, bir vektördeki 13'ü sayı değil (NAN) olarak ayarlar ve yanlış kaldırmayı gösterir (q [c (11,12,13)]) Bunu denerseniz, kaldırma işlevinin vektör numarası üzerinde çalışmadığını göreceksiniz. tüm vektörü kaldırırsınız ama belki tek bir öğeyi kaldırmazsınız.


1

Orada da subsetkullanışlı bazen olabilir ki:

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

> subset(a, !(a %in% bad))
[1]  9  7 10  6  8  1  4
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.