Skip to contents

Reshapes an ordinal response y (levels \(1, \dots, K\)) into the stacked binary-outcome, per-cut-stratified form required to fit an adjacent-category logit model as a single conditional (stratified) logistic regression, so the package's existing binary/conditional-logit fitting backends can be reused unchanged for ordinal adjacent-category models rather than needing a bespoke ordinal solver.

Usage

expand_adjacent_category_data_cpp(y, w, strata, K)

Arguments

y

Integer vector of length \(n\): each subject's ordinal category label, in 1:K.

w

Integer vector of length \(n\): a covariate (typically treatment assignment) carried through unchanged into each stacked row for that subject.

strata

Integer vector of length \(n\): positive-integer stratum/block labels; max(strata) is used as the per-cut stratum-ID offset (see Details).

K

Integer; the number of ordinal categories (so there are K - 1 adjacent-category cuts).

Value

A list with components y (stacked 0/1 binary outcome), w (stacked covariate, passed through unchanged), and strata (stacked combined stratum-by-cut ID); all three are integer vectors of the same, generally-longer-than-\(n\) length (each subject contributes 0, 1, or 2 stacked rows depending on their observed category).

Details

Model. The adjacent-category logit model compares each pair of consecutive categories \(j\) and \(j+1\) (\(j = 1, \dots, K-1\)) via $$\log\frac{\Pr(Y = j+1 \mid Y \in \{j, j+1\})}{\Pr(Y = j \mid Y \in \{j, j+1\})} = \alpha_j + \beta^\top x,$$ i.e. a logistic model for "category \(j+1\) vs. category \(j\)" fit using only the subjects actually observed in one of those two categories, with a cut-specific intercept \(\alpha_j\) and covariate effects \(\beta\) constrained equal across all \(K-1\) cuts (the proportional/parallel adjacent-category assumption). This differs from the cumulative-logit (proportional-odds) model, which instead compares \(Y \le j\) vs. \(Y > j\) using every subject at every cut.

Expansion mechanics. For each subject \(i\) and each cut \(j = 1, \dots, K-1\) (n_alpha = K - 1), a stacked row is emitted only if y[i] equals \(j\) or \(j+1\); subjects at any other level contribute nothing to that cut's comparison (so each subject contributes to at most 2 of the \(K-1\) cuts: the ones immediately adjacent to their observed level, and exactly 1 cut if at an extreme level). The stacked binary outcome is 1 if y[i] == j + 1 (upper category) and 0 if y[i] == j (lower category). The stacked stratum ID is strata[i] + (j - 1) * num_strata (where num_strata = max(strata)), i.e. the original stratum crossed with the cut index \(j\): fitting a conditional logistic regression stratified on this combined ID and pooling all stacked rows together estimates a single shared treatment coefficient \(\beta\) across all cuts, while allowing each (original stratum, cut) combination to absorb its own nuisance intercept via strata conditioning (the same stratified-conditional-logit trick used elsewhere in the package, e.g. for continuation-ratio models via expand_continuation_ratio_data_cpp()).

Input conventions. y must take integer values in 1:K (1-based category labels); w is typically the treatment indicator/covariate to estimate a coefficient for, passed through unchanged per stacked row (not itself expanded/transformed); strata must be positive integers with max(strata) == num_strata (no gaps assumed beyond that maximum, since combined stratum IDs are computed by simple integer arithmetic on num_strata, not by re-indexing distinct values). No input validation is performed at this layer (no range/type checks on y/strata); passing out-of-range values silently produces incorrect stratum IDs or drops rows rather than erroring.

See also

expand_continuation_ratio_data_cpp() for the analogous expansion used by continuation-ratio ordinal models. Ordinal regression for orientation; analogous Python API: statsmodels discrete models (no direct adjacent-category equivalent; the closest analog is fitting the expanded data as a conditional/grouped logit).