Reputation: 11480
Is there a faster/ shorter way to set values after and including match to NA ?
vec <- 1:10;vec[c(3,5,7)]<-c(NA,NaN,"remove")
#"1" "2" NA "4" "NaN" "6" "remove" "8" "9" "10"
Desired Outcome:
#"1" "2" NA "4" "NaN" "6" NA NA NA NA
My code:
vec[{grep("^remove$",vec)[1]}:length(vec)]<-NA
Please note:
In that case, we assume there will be a "remove" element prominent. So the solution does not have to take care of the case that there isn't any.
Upvotes: 2
Views: 61
Reputation: 389047
Not sure if this is shorter or faster but here is one alternative :
vec[which.max(vec == "remove"):length(vec)] <- NA
vec
#[1] "1" "2" NA "4" "NaN" "6" NA NA NA NA
Here , we find the first occurrence of "remove" using which.max
and then add NA
's till the end of the vector.
OP has mentioned that there is a "remove" element always present so we need not take care of other case however, in case we still want to keep a check we can add an additional condition.
inds <- vec == "remove"
if (any(inds)) {
vec[which.max(inds) : length(vec)] <- NA
}
Upvotes: 3
Reputation: 79238
We can also just extend the vec to the desired length:
`length<-`(vec[1:(which(vec=="remove")-1)],length(vec))
[1] "1" "2" NA "4" "NaN" "6" NA NA NA NA
Upvotes: 0
Reputation: 66819
You can use match
to stop searching after the first match is found:
m = match("remove", vec) - 1L
if (is.na(m)){
vec
} else {
c(head(vec, m), rep(vec[NA_integer_], length(vec)-m))
}
You'd have to have a pretty large vector to notice a speed difference, though, I guess. Alternately, this might prove faster:
m = match("remove", vec)
if (!is.na(m)){
vec[m:length(vec)] <- NA
}
Upvotes: 3
Reputation: 887213
We can use cumsum
on a logical vector
vec[cumsum(vec %in% "remove") > 0] <- NA
Upvotes: 2