which_first {hutilscpp} | R Documentation |
Where does a logical expression first return TRUE
?
Description
A faster and safer version of which.max
applied
to simple-to-parse logical expressions.
Usage
which_first(
expr,
verbose = FALSE,
reverse = FALSE,
sexpr,
eval_parent_n = 1L,
suppressWarning = getOption("hutilscpp_suppressWarning", FALSE),
use.which.max = FALSE
)
which_last(
expr,
verbose = FALSE,
reverse = FALSE,
suppressWarning = getOption("hutilscpp_suppressWarning", FALSE)
)
Arguments
expr |
An expression, such as |
verbose |
|
reverse |
|
sexpr |
Equivalent to |
eval_parent_n |
Passed to |
suppressWarning |
Either a |
use.which.max |
If |
Details
If the expr
is of the form LHS <operator> RHS
and LHS
is a single symbol, operator
is one of
==
, !=
, >
, >=
, <
, <=
,
%in%
,
or
%between%
,
and RHS
is numeric, then expr
is not
evaluated directly; instead, each element of LHS
is compared
individually.
If expr
is not of the above form, then expr
is evaluated
and passed to which.max
.
Using this function can be significantly faster than the alternatives
when the computation
of expr
would be expensive, though the difference is only likely to
be clear when length(x)
is much larger than 10 million.
But even for smaller vectors, it has the benefit of returning
0L
if none of the values in expr
are TRUE
, unlike
which.max
.
Compared to Position
for an appropriate
choice of f
the speed of which_first
is not much faster
when the expression is TRUE
for some position. However, which_first
is faster when all elements of expr
are FALSE
.
Thus which_first
has a smaller worst-case time than the
alternatives for most x
.
Missing values on the RHS are handled specially.
which_first(x %between% c(NA, 1))
for example is equivalent to
which_first(x <= 1)
, as in data.table::between
.
Value
The same as which.max(expr)
or which(expr)[1]
but returns 0L
when expr
has no TRUE
values.
Examples
N <- 1e5
# N <- 1e8 ## too slow for CRAN
# Two examples, from slowest to fastest,
# run with N = 1e8 elements
# seconds
x <- rep_len(runif(1e4, 0, 6), N)
bench_system_time(x > 5)
bench_system_time(which(x > 5)) # 0.8
bench_system_time(which.max(x > 5)) # 0.3
bench_system_time(which_first(x > 5)) # 0.000
## Worst case: have to check all N elements
x <- double(N)
bench_system_time(x > 0)
bench_system_time(which(x > 0)) # 1.0
bench_system_time(which.max(x > 0)) # 0.4 but returns 1, not 0
bench_system_time(which_first(x > 0)) # 0.1
x <- as.character(x)
# bench_system_time(which(x == 5)) # 2.2
bench_system_time(which.max(x == 5)) # 1.6
bench_system_time(which_first(x == 5)) # 1.3