Skip to contents

Compute a position-wise logical AND across multiple logical inputs, allowing up to a specified fraction of missing values before returning NA.

Usage

and(..., .na_allowed = 0.2)

Arguments

...

Logical vectors of equal length, or a single logical matrix/data.frame. Matrix/data.frame inputs must have at least one column. Inputs are coerced to logical via as.logical, preserving NA.

.na_allowed

(Scalar numeric: 0.2; [0, 1])
Maximum allowed fraction of NA per position before the result is set to NA when no input is FALSE.

Value

A logical vector with values TRUE, FALSE, or NA per the rule in Details.

Details

This is a tolerance-aware variant of logical conjunction over multiple inputs (e.g., x & y & z). Each output position corresponds to one vector index, or to one row when a matrix or data.frame is supplied. The result is FALSE when any input at that position is FALSE. Otherwise, the result is NA when the fraction of missing values exceeds .na_allowed. If the missing fraction is within tolerance, missing values are treated as TRUE and the result is TRUE.

For each position (row) \(i\) across \(p\) inputs, let \(m_i\) be the number of NAs and \(f_i\) be the number of FALSEs. Define the missing fraction \(r_i = m_i / p\). Then: $$ \text{and}_i = \begin{cases} \mathrm{NA}, & \text{if } r_i > \text{.na\_allowed} \text{ and } f_i = 0, \\ \text{TRUE}, & \text{if } r_i \le \text{.na\_allowed} \text{ and } f_i = 0, \\ \text{FALSE}, & \text{if } f_i \ge 1. \end{cases} $$

Notes:

  1. When .na_allowed = 0, behavior matches strict AND: NAs propagate only when no input is FALSE.

  2. When \(\text{.na\_allowed} = 1\), missingness never forces NA. NAs are treated as TRUE, so the result is FALSE iff any FALSE is present, otherwise TRUE.

See also

Examples

#----------------------------------------------------------------------------
# and() examples
#----------------------------------------------------------------------------
library(bkbase)

x <- c(TRUE, TRUE, TRUE, FALSE, TRUE)
y <- c(TRUE, TRUE, NA, TRUE, NA)
z <- c(TRUE, NA, TRUE, TRUE, NA)

# Base R strict AND
x & y & z
#> [1]  TRUE    NA    NA FALSE    NA

# NA tolerance at 20%
and(x, y, z, .na_allowed = 0.2)
#> [1]  TRUE    NA    NA FALSE    NA

# NA tolerance at 40%
and(x, y, z, .na_allowed = 0.4)
#> [1]  TRUE  TRUE  TRUE FALSE    NA

# Single data.frame input
df <- data.frame(x = x, y = y, z = z)
and(df, .na_allowed = 0.4)
#> [1]  TRUE  TRUE  TRUE FALSE    NA

# FALSE dominates even when NA is present
and(FALSE, NA, .na_allowed = 0)
#> [1] FALSE