minicase provides a single function, mcase_case_when(), a minimal reimplementation of dplyr::case_when(): vectorised if/else across a sequence of condition ~ value formulas, first match wins. See the README for scope notes; this page walks through it on the same toy fruits data frame used in the minifilter vignette, building up to how missing values and default values interact.
Functions
mcase_case_when(...) – given a sequence of condition ~ value formulas, return a vector the same length as the (recycled) conditions/values, taking the value from the first formula whose condition is TRUE at each position, and NA wherever no condition matched.
minicase has five internal helpers (.mcase_validate_length(), .mcase_replace_with(), .mcase_check_length(), .mcase_check_type(), .mcase_check_class()), all supporting mcase_case_when()’s recycling and type-consistency checks – there’s no need to call any of them directly.
name price in_stock
1 apple 1.2 TRUE
2 banana 0.5 TRUE
3 cherry 3.0 FALSE
4 date NA TRUE
5 elderberry 4.5 TRUE
No data-masking: reference columns with $, or wrap in with()
Unlike dplyr::case_when(), conditions and values are evaluated in the caller’s environment, not the data frame’s – so bare column names don’t resolve on their own. The idiomatic way around that, mirrored here from base R, is to wrap the whole call in with(data, ...), which temporarily makes the data frame’s columns available as bare names for the duration of the call:
Formulas are checked in order, and the first TRUE condition for each position determines its value, even if a later condition would also match. cherry (price 3.00) is a good illustration: it fails price < 3, but matches price >= 3, so it’s classified as "pricey" above. Conditions can combine several tests with &, which is useful for layering more specific rules ahead of more general ones:
with(fruits, mcase_case_when( in_stock & price <1~"cheap and in stock", in_stock ~"in stock",TRUE~"out of stock or unknown price"))
[1] "in stock" "cheap and in stock"
[3] "out of stock or unknown price" "in stock"
[5] "in stock"
banana matches both the first and second formula here (it’s in stock and under $1), but because the first-match-wins rule checks formulas top to bottom, it’s classified by the more specific "cheap and in stock" rule rather than the more general "in stock" one. Ordering formulas from most to least specific is exactly how you get that behaviour deliberately, rather than by accident.
Unmatched positions are NA
date has a missing price, so every condition involving price evaluates to NA for that row – neither TRUE nor FALSE – and date itself gets NA in the result, since there’s no condition it definitively satisfies:
Add a TRUE ~ ... formula at the end as a catch-all default, the same way you would in dplyr, and every remaining position – including ones where every prior condition was NA rather than FALSE – picks up that value instead:
That trailing TRUE ~ "unknown" formula is the idiomatic way to get a default in both dplyr::case_when() and mcase_case_when() – minicase just doesn’t implement dplyr’s newer, separate .default argument as an alternative spelling of the same thing, nor .ptype/ .size for controlling the output type/length explicitly. If your use case needs those, a plain TRUE ~ value formula covers .default, and the output length/type simply follow from whatever the conditions and values recycle to, the same way base R vector recycling works elsewhere.