*! version 1.0 March 2026

Title

ineqop -- Inequality of opportunity decomposition using direct, indirect, and Shapley approaches

Syntax

ineqop
depvar
[if] [in]
[weight]
, type(varlist) [options]

Required
type(varlist) one or more circumstance variables defining types

Indices
gini include the Gini index (default)

nogini exclude the Gini index

ge(numlist) GE indices to compute; default is ge(-1 0 1 2)

Output
pattern produce 2x2 figure of IO shares across indices for one group

bypattern produce combined 2x2 figure of IO shares over by-groups (use with bys)

contributions produce stacked bar chart of Shapley RIF contributions by type

contrtable display table with Shapley RIF contributions by type

contrindex(string) index for contributions graph; default is gini

descriptives display table with distribution of circumstance variables

trend plot trends of inequality levels and IO shares over by-groups (use with bys)

trendindex(string) index for trend levels graph; default is gini

generate(namelist) generate variables for smoothed (y_b) and standardized (y_w) distributions

lorenz produce Lorenz curve graphs (direct and Shapley)

detail show additional details (e.g., BM decomposition for Gini)

all turn on all output options at once

Formatting
format(string) display format for levels; default is %9.4f

formatp(string) display format for percentages; default is %9.1f

aweights, fweights, and iweights are allowed;
see weight.

by is allowed; see by.

Description

ineqop estimates the contribution of birth circumstances (inequality of
opportunity, IO) to overall inequality, following the methodology in
Gradin and Zapata Roman (2026).

The program decomposes total inequality into between-type inequality
(inequality of opportunity, IO) and within-type inequality (residual
inequality, IR), where types are defined by combinations of observable
circumstances beyond individual control (e.g., gender, parental education,
ethnicity, region of birth).

Three approaches are reported:

1. Direct approach (IOD): IO is measured as inequality
in the smoothed distribution y_b where each person's income is replaced
by their type mean. The remaining inequality I(y) - I(y_b) is attributed
to residual factors.

2. Indirect approach (IOI): IO is measured as the
reduction in inequality after equalizing type means (standardized distribution
y_w). That is, IOI = I(y) - I(y_w).

3. Shapley approach (IOs): The average of direct and
indirect measures, splitting the interaction term equally between IO and IR:
I_sb = I(y_b) + (1/2)*I_bw, where
I_bw = I(y) - I(y_b) - I(y_w).

For path-independent measures (MLD), all three approaches give the same result.
For path-dependent measures (Gini, Theil, etc.), they can differ substantially
due to the interaction term.

The program also supports RIF-based decomposition of each type's contribution
to IO and IR using the Shapley approach (Figure 6 in the paper).

Options

Required

type(varlist) specifies one or more variables defining the types
(population groups sharing the same circumstances). If a single variable is
specified, it is used directly as the type variable. If multiple variables are
specified, the program creates types from all observed combinations using
egen group().

Indices

gini includes the Gini index in the decomposition. This is the default.

nogini excludes the Gini index.

ge(numlist) specifies the alpha values for the Generalized Entropy
indices to compute. The default is ge(-1 0 1 2), corresponding to
GE(-1), MLD (GE(0)), Theil (GE(1)), and half the squared coefficient of
variation (GE(2)).

Output

pattern produces a combined 2x2 figure with four panels, mirroring the
layout of Figure 2 in Gradin and Zapata Roman (2026):
(a) Direct IOD, (b) Indirect IOI, (c) Interaction I_bw/I(y), and
(d) Shapley IOs. Each panel plots the IO share (as % of overall
inequality) across the computed GE indices using connected markers along the
alpha axis, showing how IO varies with the sensitivity parameter. The
Gini index, being a different family, is shown as a separate standalone marker
(diamond). When used with bys year:, one combined figure is produced per
group, allowing the user to compare patterns over time.

bypattern produces a combined 2x2 figure similar to pattern but
accumulating results across all by-groups (e.g., years) and drawing them
together in a single figure. Each panel (Direct IOD, Indirect IOI,
Interaction I_bw/I(y), Shapley IOs) shows connected lines with different
colors and markers for each computed index (Gini, MLD, Theil, etc.), with the
by-variable values (e.g., years) along the horizontal axis.
This option requires the use of bys (e.g., bys year:).
The combined figure is produced after the last by-group is processed.

contributions produces a stacked bar chart showing the Shapley
contribution of each type to IO (between) and IR (within) as a percentage of
overall inequality. Types are sorted in descending order by their IO
contribution. The index used for the graph is determined by contrindex().
Also displays the contributions table.

contrtable displays a table with the Shapley RIF contributions of each
type to IO and IR for all selected indices, without producing a graph.

contrindex(string) specifies which inequality index to use for the
contributions graph. Valid values are gini (default), ge-1,
ge0, ge1, or ge2, provided the corresponding index is
being computed. For example, contrindex(ge1) produces the graph using
the Theil index.

descriptives displays a table with the weighted distribution (percentage)
of each circumstance variable specified in type(), as in Table A2 of
Gradin and Zapata Roman (2026). For each variable, the percentage of each
category in the (weighted) population is shown, along with the total sample
size. When used with bys, results are accumulated across by-groups and
a single combined table is displayed after the last group, with one column per
by-group value (e.g., year). Without bys, a single-column table is
displayed.

trend produces two trend figures that accumulate results across by-groups
(e.g., years), as in Figures 3 and 4 of Gradin and Zapata Roman (2026).
This option requires the use of bys (e.g., bys year:).
The first figure (trend_levels) plots the evolution of inequality levels
for one index: I(y), I(y_b), and I(y_w) as solid connected lines, and the
Shapley values I_sb and I_sw as dashed connected lines.
The second figure (trend_shares) plots the Shapley IO share (IOs,
as % of overall inequality) for all computed indices on the same graph,
showing how the contribution of circumstances varies over time across indices.

trendindex(string) specifies which inequality index to use for the
trend levels figure (first figure). Valid values are gini (default),
ge-1, ge0, ge1, or ge2. For example,
trendindex(ge0) plots MLD levels over time.

generate(namelist) creates two new variables containing the smoothed
(y_b) and standardized (y_w) distributions. Exactly two variable
names must be specified: the first for y_b (each observation replaced by
its type mean) and the second for y_w (rescaled so all types have the
overall mean). For example, gen(yb yw) creates variables yb and
yw.

lorenz produces two Lorenz curve figures, as in Figure A3 of Gradin and
Zapata Roman (2026). The first figure (lorenz_a) plots the empirical
Lorenz curves for the overall (y), between-type (y_b, smoothed), and
within-type (y_w, standardized) distributions, along with the 45-degree
line. The second figure (lorenz_b) plots the Shapley Lorenz curves:
L_sb(p) = L_b(p) + (1/2)[L(p) - L_b(p) - L_w(p)] and
L_sw(p) = L_w(p) + (1/2)[L(p) - L_b(p) - L_w(p)], along with the
overall Lorenz curve L(y). These satisfy L(y) = L_sb + L_sw.

detail shows additional decomposition details, including the
Bhattacharya-Mahalanobis (BM) within-group weighted sum and residual for the
Gini index.

all activates all output options at once: pattern, bypattern,
contributions, contrtable, descriptives, trend,
lorenz, and detail. This is a convenience shortcut equivalent to
specifying each option individually. The default indices
(contrindex(gini), trendindex(gini)) apply unless overridden.
Note that generate() must be specified separately if desired.

Formatting

format(string) specifies the display format for index levels.
Default is %9.4f.

formatp(string) specifies the display format for percentages.
Default is %9.1f.

Stored results

ineqop stores the following in r():

Scalars (for each index X = G, GEm1, GE0, GE1, GE2)

r(X_y) overall inequality I(y)

r(X_yb) between-type inequality I(y_b)

r(X_yw) within-type inequality I(y_w)

r(X_Ibw) interaction term I_bw

r(X_Isb) Shapley between-type I_sb

r(X_Isw) Shapley within-type I_sw

r(X_IOD) direct IO share (% of overall)

r(X_IOI) indirect IO share (% of overall)

r(X_IOs) Shapley IO share (% of overall)

Matrices

r(results) summary matrix with all decomposition results

Examples

Basic decomposition from circumstance variables:

. ineqop y [aw=weight], type(gender educ_parents region ethnicity)

Decomposition with a pre-created type variable:

. ineqop y [aw=weight], type(type)

Decomposition for all years using bys:

. bys year: ineqop y [aw=weight], type(type)

IO shares across indices (pattern graph):

. ineqop y [aw=weight], type(type) pattern

With detailed BM decomposition for Gini:

. ineqop y [aw=weight], type(type) detail

With Shapley RIF contributions graph (Gini, default):

. ineqop y [aw=weight], type(type) contributions

Contributions graph using the Theil index:

. ineqop y [aw=weight], type(type) contributions contrindex(ge1)

Table of RIF contributions only (no graph):

. ineqop y [aw=weight], type(type) contrtable

Only entropy measures (no Gini), custom alphas:

. ineqop y [aw=weight], type(type) nogini ge(0 1)

Distribution of circumstances for all years:

. bys year: ineqop y [aw=weight], type(gender educ_parents region ethnicity) descriptives

Combined IO pattern across all years:

. bys year: ineqop y [aw=weight], type(type) bypattern

Trend of Gini levels and IO shares over time:

. bys year: ineqop y [aw=weight], type(type) trend

Trend using MLD levels:

. bys year: ineqop y [aw=weight], type(type) trend trendindex(ge0)

Generate smoothed and standardized distributions:

. ineqop y [aw=weight], type(type) gen(yb yw)

Lorenz curves (direct and Shapley):

. ineqop y [aw=weight], type(type) lorenz

Everything at once for all years:

. bys year: ineqop y [aw=weight], type(gender educ_parents region ethnicity) all

References

Gradin, C. and Zapata-Roman, G. (2026). Unpacking the contribution of birth
circumstances to inequality using a Shapley decomposition: the case of Chile.
Review of Income and Wealth, forthcoming (open access).

Shorrocks, A.F. (2013). Decomposition procedures for distributional analysis:
a unified framework based on the Shapley value.
Journal of Economic Inequality, 11, 99-126.

Chantreuil, F. and Trannoy, A. (2013). Inequality decomposition values: the
trade-off between marginality and efficiency.
Journal of Economic Inequality, 11, 83-98.

Foster, J.E. and Shneyerov, A.A. (2000). Path independent inequality measures.
Journal of Economic Theory, 91(2), 199-222.

Firpo, S., Fortin, N. and Lemieux, T. (2009). Unconditional quantile
regressions. Econometrica, 77(3), 953-973.

Author

Carlos Gradin

Universidade de Vigo

Email: cgradin@uvigo.gal

This code was developed with the assistance of AI tools; all code has been reviewed, tested with the paper's original data, and validated by the author.

Also see

Help: iop (if installed)