Skip to contents

A thin, survey-friendly wrapper around base::cut() that returns a factor in band order and uses left-closed, right-open intervals by default so that age bands like 18-21 behave intuitively. Generalises the case_when(age %in% seq(...)) age-grouping pattern.

Usage

bin_numeric(x, breaks, labels, right = FALSE, quiet = FALSE)

Arguments

x

A numeric vector.

breaks

Numeric vector of cut points. With n labels you need n + 1 breaks. Use Inf for an open-ended top band.

labels

Character vector of group labels, length length(breaks) - 1.

right

If TRUE, intervals are closed on the right; if FALSE (default) closed on the left. Left-closed matches "18 to 21" style bands.

quiet

If TRUE, do not report values that fell outside breaks.

Value

A factor whose levels are labels in the order given (values outside the range or NA become NA).

Details

Bands are built with base::cut() using include.lowest = TRUE, so the very lowest break is included. With right = FALSE (the default) a band runs from its lower break up to but not including the next – i.e. [18, 25) – which is what you want for age groups like "18 to 24". Text input is salvaged with ensure_numeric(), so "27 years" bins correctly. The result is a factor whose levels follow labels, so tables and charts built from it list the bands low to high ("40-70k" before "100-150k") rather than alphabetically. Wrap it in as.character() if you need plain text.

A value below the first break or above the last becomes NA and drops out of every chart built from the result, so the function says how many did and what their range was. A closed top band such as 35 to 40.5 under a label of "35 to 40+" is the usual cause; Inf is what that label means.

Examples

bin_numeric(c(15, 19, 27, 41),
            breaks = c(0, 18, 25, 35, Inf),
            labels = c("<18", "18-24", "25-34", "35+"))
#> [1] <18   18-24 25-34 35+  
#> Levels: <18 18-24 25-34 35+