I have a question about a vectorized operation with logical vectors. In my problem, there are two vectors: main and secondary. They're both of the same length. I want to replace some elements in the main vector to NA
, based on insights I gather from the secondary vector.
- The main vector is comprised of
TRUE
andFALSE
that can appear in any random order. - The secondary vector is either:
- a sequence of
TRUE
then a sequence ofFALSE
with/withoutNA
as the last element; or - all
TRUE
; or - all
FALSE
; or - all
FALSE
with last element asNA
; or - all
TRUE
with last element asNA
- a sequence of
I'll provide several examples below and explain the desired algorithm.
A - The most common case
replace x
values with NA
for positions that are FALSE
in y
# here, `x` is the main vector
x <- c(FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, NA)
# `y` is the secondary vector
y <- c(TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE)
# `z` is the desired output
z <- c(FALSE, FALSE, TRUE, FALSE, FALSE, NA, NA) # in this case only index 7 in `x` actually changed
B - The secondary vector is all FALSE
x2 <- c(FALSE, NA)
y2 <- c(FALSE, FALSE)
# desired output
z2 <- c(NA, NA)
C - The secondary vector is all TRUE
x3 <- rep(FALSE, 4)
y3 <- rep(TRUE, 4)
# desired output
z3 <- rep(FALSE, 4)
My attempt
I've almost figured this out, but unfortunately it fails with scenario B.
my_func <- function(main, secondary) {
idx_last_true_in_secondary <- max(which(secondary))
if(idx_last_true_in_secondary == length(secondary)) {
return(main)
}
main[(idx_last_true_in_secondary 1): length(main)] <- NA
main
}
# case A
my_func(x, y)
#> [1] FALSE FALSE TRUE FALSE FALSE NA NA
# case B
my_func(x2, y2)
#> Warning in max(which(secondary)): no non-missing arguments to max; returning
#> -Inf
#> Error in (idx_last_true_in_secondary 1):length(main): result would be too long a vector
# case C
my_func(x3, y3)
#> [1] FALSE FALSE FALSE FALSE
My question is whether anyone sees a better way to approach the problem?
CodePudding user response:
We could do it this way:
my_func <- function(x, y) {
replace(x, !y, NA)
}
How it works:
# A
replace(x, !y, NA)
[1] FALSE FALSE TRUE FALSE FALSE NA NA
# B
replace(x2, !y2, NA)
[1] NA NA
# C
replace(x3, !y3, NA)
[1] FALSE FALSE FALSE FALSE
my_func(x,y)
my_func(x2,y2)
my_func(x3,y3)
output:
> my_func(x,y)
[1] FALSE FALSE TRUE FALSE FALSE NA NA
> my_func(x2,y2)
[1] NA NA
> my_func(x3,y3)
[1] FALSE FALSE FALSE FALSE
CodePudding user response:
This seems to work as expected:
my_func <- function(main,secondary ) {
main[!secondary] <- NA
return(main)
}
my_func(x,y)
[1] FALSE FALSE TRUE FALSE FALSE NA NA
my_func(x2,y2)
[1] NA NA
my_func(x3,y3)
[1] FALSE FALSE FALSE FALSE
CodePudding user response:
We can try ifelse
like below
> ifelse(y,x,NA)
[1] FALSE FALSE TRUE FALSE FALSE NA NA