Як видалити декілька значень з вектора?


125

У мене такий вектор, як: a = c(1:10)і мені потрібно видалити декілька значень, наприклад:2, 3, 5

Як видалити ці числа (вони НЕ позиції у векторі) у векторі?

на даний момент я петлю вектор і роблю щось на кшталт:

a[!a=NUMBER_TO_REMOVE]

Але я думаю, що є функція, яка робить це автоматично.

Відповіді:


192

%in%Оператор каже вам , які елементи є одними з numers видалити:

> 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

Зверніть увагу, що це мовчки видалить непорівнянні (такі речі, як NAі Inf)добре (в той час як вони зберігатимуть повторювані значення до aтих пір, поки вони не вказані в remove).

  • Якщо aможе містити незрівнянні, але removeне буде, ми можемо використовувати match, кажучи, щоб повернутись 0за невідповідністю та незрівнянними ( %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 = 0не потрібен, оскільки незрівнянні все одно не збігаються, але я б включив його заради читабельності.
    Це, до речі, те, що setdiffробиться всередині (але без того, uniqueщоб викидати дублікати, в aякі не знаходяться remove).

  • Якщо removeмістяться непорівнянні, вам доведеться перевіряти їх окремо, наприклад

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

    (Це не відрізняється NAвід, NaNале керівництво R все одно попереджає, що не слід покладатися на наявність різниці між ними)

    Для Inf/ -Infвам доведеться перевірити і те, signіis.finite


1
setdiffкраще, оскільки він робить все за одну операцію і посилається на поправлений вектор лише один раз.
Олекса

1
@Olexa: різниця заданих параметрів не завжди така ж, як видалення всіх випадків заданого набору чисел з вектора: вона видалить дублікати, у aяких також немає remove. Якщо це не проблема, ви також можете використовувати setdiff. setdiff, btw, використовує matchдля цього %in%ярлик.
cbeleites незадоволений SX

97

Можна використовувати setdiff.

Дано

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

Тоді

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

1
дуже корисно, коли aце результат іншої функції, щоб ви могли робити речі в одному рядку замість 3 та тимчасової змінної
jf328

14
Це дасть інші результати, ніж %in%рішення, якщо вектор введення містить дублікати (у такому випадку setdiffповертається лише унікальний набір , тобто без дублікатів)
talat

2
@docendodiscimus: fsetdiffз data.tableпакета має allпрапор ( по замовчуванням F) , що дозволяє зберегти дублікати у вхідному векторі.
Юрген

9

Ви можете це зробити так:

> 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

Незабаром

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

1
те, що ви називаєте списком у своєму прикладі, є вектором, правда?
Патрік

Так, я маю на увазі вектор. Дякуємо за коментар
ykpemre

Тут немає потреби which. Це в основному те саме, що і відповідь @cbeleites.
Девід Аренбург

так, це схоже, але відрізняється в кількох точках зору. whichповертає індекси істинних значень. Отже, знак мінус може використовуватися для того, щоб сказати "індекси, окрім цих індексів". Крім того, whichвона легше читається, оскільки вона ближче до природної мови.
ykpemre

4

замість

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

використовуючи пакети, purrrі magrittrви можете:

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

це дозволяє subsetвикористовувати ting, використовуючи ім'я вектора лише один раз. І ви можете використовувати його в трубах :)


чи можете ви пояснити своє останнє твердження про довжину імені змінних? Чому вам це не подобається? Чому краще, ніж інший шлях? Або видаліть цей абзац, оскільки він не пов'язаний з головним питанням / питанням.
rodrigoap

2

Спочатку ми можемо визначити нового оператора,

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

Тоді, як x не у видаленні

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

або навіщо йти на видалення, перейдіть безпосередньо

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

3
Питання конкретно говорить, що 2, 3 і 5 не є позиціями у векторі.
blakeoft

1

ОНОВЛЕННЯ:

Усі вищезазначені відповіді не працюватимуть для повторних значень, відповідь @ BenBolker за допомогою duplicated()предиката вирішує це:

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

Оригінальний відповідь: тут я пишу для цього невелику функцію:

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

так, скажімо, full_vector=c(1,2,3,4,1)і searched_vector=c(1,2,3).

exclude_val(full_vector,searched_vector)повернеться (4,1), однак вищевказані відповіді повернуться просто (4).


1
про що full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]?
Бен Болкер

@BenBolker ах, я не знав, що "дублюється" присудок: ((що тепер, я можу видалити свою відповідь чи змінити її, щоб натомість показати лише свою?
Özgür

@BenBolker, ваше рішення неправильне; просто спробуйте: full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3);- що створює 1, 1, 2замість правильної відповіді 1, 2.
fnl

Просто для додання можливого правильного рішення для повторних значень: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

Це встановлює 13 у векторі не число (NAN), воно показує помилкове видалення (q [c (11,12,13)]), якщо ви спробуєте це, ви побачите, що функція видалення не працює на векторному номері. ви видаляєте весь вектор, але, можливо, не один елемент.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.