Làm thế nào để xóa nhiều giá trị từ một vectơ?


125

Tôi có một vectơ như: a = c(1:10)và tôi cần xóa nhiều giá trị, như:2, 3, 5

Làm thế nào để xóa những số đó (chúng KHÔNG phải là vị trí trong vectơ) trong vectơ?

tại thời điểm tôi lặp vector và làm một cái gì đó như:

a[!a=NUMBER_TO_REMOVE]

Nhưng tôi nghĩ có một chức năng thực hiện nó tự động.

Câu trả lời:


192

Các %in%nhà điều hành sẽ cho bạn biết các yếu tố là một trong những numers để loại bỏ:

> 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

Lưu ý rằng điều này sẽ âm thầm loại bỏ những thứ không thể so sánh được (thứ tương tự NAhoặc Inf)tốt (trong khi nó sẽ giữ các giá trị trùng lặp amiễn là chúng không được liệt kê trong remove).

  • Nếu acó thể chứa không thể so sánh được, nhưng removesẽ không, chúng ta có thể sử dụng match, yêu cầu nó trả lại 0cho các kết quả không khớp và không thể so sánh được ( %in%là một phím tắt thông thường cho 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 = 0không cần thiết vì dù sao cũng không thể so sánh được, nhưng tôi bao gồm nó vì mục đích dễ đọc.
    Đây là, btw., Những gì setdifflàm trong nội bộ (nhưng không có uniqueđể loại bỏ các bản sao trong ađó không có trong remove).

  • Nếu removechứa không thể so sánh được, bạn sẽ phải kiểm tra riêng lẻ, vd

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

    (Điều này không phân biệt NAvới NaNnhưng dù sao thì hướng dẫn sử dụng R cảnh báo rằng người ta không nên dựa vào việc có sự khác biệt giữa chúng)

    Cho Inf/ -Infbạn sẽ phải kiểm tra cả hai signis.finite


1
setdifflà tốt hơn, vì nó thực hiện mọi thứ trong một thao tác và chỉ tham chiếu vectơ đã sửa đổi một lần.
Olexa

1
@Olexa: sự khác biệt của tập hợp không phải lúc nào cũng giống như loại bỏ tất cả các lần xuất hiện của một tập hợp số đã cho khỏi một vectơ: nó sẽ loại bỏ các bản sao trong ađó không removegiống nhau. Nếu đó không phải là một vấn đề, bạn cũng có thể sử dụng setdiff. setdiff, Btw, sử dụng match%in%là một phím tắt.
cbeleites không hài lòng với SX

97

Bạn có thể sử dụng setdiff.

Được

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

Sau đó

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

1
rất hữu ích khi alà kết quả của một chức năng khác để bạn có thể thực hiện mọi việc trong một dòng thay vì 3 và biến tạm thời
jf328

14
Điều này sẽ tạo ra kết quả khác nhau hơn so với %in%giải pháp nếu vector đầu vào chứa bản sao (trong trường hợp này setdiffsẽ chỉ trả lại độc đáo bộ , tức là không có bản sao)
Talat

2
@docendodiscimus: fsetdiffcủa data.tablegói có allcờ (F mặc định) cho phép giữ các bản sao trong vectơ đầu vào.
Juergen

9

Bạn có thể làm như sau:

> 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

Một thời gian ngắn

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

1
những gì bạn đang gọi một danh sách trong ví dụ của bạn là một vectơ, phải không?
patrick

Vâng, ý tôi là vectơ. Cảm ơn các bình luận.
ykpemre

Không có nhu cầu ở whichđây. Về cơ bản, nó giống như câu trả lời của @cbeleites.
David Arenburg

vâng nó tương tự, nhưng khác nhau ở một vài quan điểm. whichtrả về các chỉ mục của các giá trị TRUE. Vì vậy, dấu trừ có thể được sử dụng để nói "các chỉ mục khác với các chỉ mục này". Cũng whichdễ đọc hơn vì nó gần với ngôn ngữ tự nhiên hơn.
ykpemre

4

thay vì

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

sử dụng các gói purrrmagrittr, bạn có thể làm:

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

điều này cho phép subsetting sử dụng tên vector chỉ một lần. Và bạn có thể sử dụng nó trong đường ống :)


bạn có thể vui lòng giải thích tuyên bố cuối cùng của bạn về độ dài tên biến? Tại sao bạn không thích điều đó? Tại sao tốt hơn so với cách khác? Hoặc, xóa đoạn đó vì không liên quan đến vấn đề / câu hỏi chính.
Rodrigoap

2

Đầu tiên chúng ta có thể định nghĩa một toán tử mới,

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

Sau đó, nó giống như x không loại bỏ

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

hoặc tại sao phải đi để loại bỏ, đi trực tiếp

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

3
Câu hỏi đặc biệt nói rằng 2, 3 và 5 không phải là vị trí trong vectơ.
blakeoft

1

CẬP NHẬT:

Tất cả các câu trả lời trên sẽ không hoạt động đối với các giá trị được lặp lại, câu trả lời @ BenBolker sử dụng duplicated()vị ngữ giải quyết điều này:

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

Câu trả lời gốc: ở đây tôi viết một hàm nhỏ cho việc này:

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

vì vậy, hãy nói full_vector=c(1,2,3,4,1)searched_vector=c(1,2,3).

exclude_val(full_vector,searched_vector)sẽ trả về (4,1), tuy nhiên câu trả lời ở trên sẽ trả về (4).


1
những gì về full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]?
Ben Bolker

@BenBolker ah Tôi không biết rằng vị từ "trùng lặp": (bây giờ tôi sẽ xóa câu trả lời của mình hoặc thay đổi nó để chỉ hiển thị của bạn thay vào đó?
Özgür

@BenBolker, giải pháp của bạn sai; chỉ cần thử: full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3);- mà tạo ra 1, 1, 2thay vì câu trả lời đúng 1, 2.
fnl

Chỉ cần thêm một giải pháp có thể, chính xác cho các giá trị lặp lại: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

Điều này đặt 13 trong một vectơ thành một số (NAN), nó hiển thị xóa sai (q [c (11,12,13)]) nếu bạn thử điều này, bạn sẽ thấy hàm loại bỏ không hoạt động trên số vectơ. bạn loại bỏ toàn bộ vector nhưng có thể không phải là một yếu tố duy nhất.


1

subsetĐôi khi cũng có thể hữu ích:

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

> subset(a, !(a %in% bad))
[1]  9  7 10  6  8  1  4
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.