How to delete multiple values from a vector?
RR Problem Overview
I have a vector like: a = c(1:10)
and I need to remove multiple values, like: 2, 3, 5
How to delete those numbers (they are NOT the positions in the vector) in the vector?
at the moment i loop the vector and do something like:
a[!a=NUMBER_TO_REMOVE]
But I think there is a function that does it automatically.
R Solutions
Solution 1 - R
The %in%
operator tells you which elements are among the numers to remove:
> 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
Note that this will silently remove incomparables (stuff like NA
or Inf)
as well (while it will keep duplicate values in a
as long as they are not listed in remove
).
-
If
a
can contain incomparables, butremove
will not, we can usematch
, telling it to return0
for non-matches and incomparables (%in%
is a conventient shortcut formatch
):> 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
is not needed as incomparables will anyways not match, but I'd include it for the sake of readability.
This is, btw., whatsetdiff
does internally (but without theunique
to throw away duplicates ina
which are not inremove
). -
If
remove
contains incomparables, you'll have to check for them individually, e.g.if (any (is.na (remove))) a <- a [! is.na (a)]
(This does not distinguish
NA
fromNaN
but the R manual anyways warns that one should not rely on having a difference between them)For
Inf
/-Inf
you'll have to check bothsign
andis.finite
Solution 2 - R
You can use setdiff
.
Given
a <- sample(1:10)
remove <- c(2, 3, 5)
Then
> a
[1] 10 8 9 1 3 4 6 7 2 5
> setdiff(a, remove)
[1] 10 8 9 1 4 6 7
Solution 3 - R
You can do it as follows:
> 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
Shortly
> x = x[ - which(x %in% y)]
Solution 4 - R
instead of
x <- x[! x %in% c(2,3,5)]
using the packages purrr
and magrittr
, you can do:
your_vector %<>% discard(~ .x %in% c(2,3,5))
this allows for subset
ting using the vector name only once. And you can use it in pipes :)
Solution 5 - R
First we can define a new operator,
"%ni%" = Negate( "%in%" )
Then, its like x not in remove
x <- 1:10
remove <- c(2,3,5)
x <- x[ x %ni% remove ]
or why to go for remove, go directly
x <- x[ x %ni% c(2,3,5)]
Solution 6 - R
There is also subset
which might be useful sometimes:
a <- sample(1:10)
bad <- c(2, 3, 5)
> subset(a, !(a %in% bad))
[1] 9 7 10 6 8 1 4
Solution 7 - R
UPDATE:
All of the above answers won't work for the repeated values, @BenBolker's answer using duplicated()
predicate solves this:
full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]
Original Answer: here I write a little function for this:
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)
}
so, let's say full_vector=c(1,2,3,4,1)
and searched_vector=c(1,2,3)
.
exclude_val(full_vector,searched_vector)
will return (4,1), however above answers will return just (4)
.
Solution 8 - R
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
This sets the 13 in a vector to not a number(NAN) it shows false remove(q[c(11,12,13)]) if you try this you will see that remove function don't work on vector number. you remove entire vector but maybe not a single element.