Instead of subsetting x with b the FALSE positions could be set to NA using [<-.
which.min("[<-"(x, !b, NA))
#[1] 5
Alternatively it could also be set to e.g. Inf, as given in the answer from @mrflick, but this will limit the general applicability, to use for which.max it need to be set to -Inf and in case of no TRUE it will return an index.
The logical vector could be converted to indices by using which and those indices could be used for subsetting and be subseted, similar to the solution of @mrflick, but avoiding using which twice.
i <- which(b)
i[which.min(x[i])]
#[1] 5
In case the values in x are all positive you can divide by b what gives for the cases of b == FALSE Inf (and in case of negative x -Inf) - This way is not recommended.
which.min(x / b)
#[1] 5
Comparing with bench::mark:
n <- 1e6
set.seed(42)
x <- sample(0:99, n, TRUE)
b <- sample(c(TRUE,FALSE), n, TRUE)
bench::mark(which.min(ifelse(b, x, Inf))
, which(b)[which.min(x[b])]
#, which(x == min(x[b])) #Result not equal to others
#, which(x == min(x[b]) & b) #Result not equal to others
, which.min("[<-"(x, !b, NA))
, which.min("[<-"(x, !b, Inf))
, which.min(x / b)
)
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm>
#1 which.min(ifelse(b, x, Inf)) 13.75ms 13.95ms 70.6 30.52MB 61.2 15 13 212ms
#2 which(b)[which.min(x[b])] 5.13ms 5.2ms 192. 19.07MB 92.5 58 28 303ms
#3 which.min(`[<-`(x, !b, NA)) 3.58ms 3.67ms 271. 11.44MB 51.2 106 20 391ms
#4 which.min(`[<-`(x, !b, Inf)) 4.85ms 4.96ms 200. 19.07MB 100. 50 25 250ms
#5 which.min(x/b) 3.99ms 4.05ms 246. 7.63MB 22.6 109 10 442ms
b <- logical(n) #No True
bench::mark(#which.min(ifelse(b, x, Inf)) #Wrong result
which(b)[which.min(x[b])]
, which.min("[<-"(x, !b, NA))
#, which.min("[<-"(x, !b, Inf)) #Wrong result
#, which.min(x / b) #Wrong result
)
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result
# <bch:expr> <bch:> <bch:> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list>
#1 which(b)[which.min(x[b])] 1.18ms 1.21ms 826. 7.63MB 72.9 340 30 412ms <int …
#2 which.min(`[<-`(x, !b, NA)) 5.36ms 5.49ms 181. 15.26MB 38.3 71 15 392ms <int …
b <- !logical(n) #All True
bench::mark(which(b)[which.min(x[b])]
, which.min("[<-"(x, !b, NA))
)
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result
# <bch:expr> <bch:> <bch:> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list>
#1 which(b)[which.min(x[b])] 5.06ms 5.25ms 184. 19.1MB 92.0 54 27 293ms <int …
#2 which.min(`[<-`(x, !b, NA)) 3.59ms 3.81ms 261. 11.4MB 48.5 102 19 391ms <int …