*! version 1.0.0 \ Daniel Krähmer \ May 2023

Title

mfcurve -- Plotting results from multifactorial research designs

Syntax

mfcurve varname,
factors(varlist)
[options]

groupvar(varname) determine groups based on variable varname

test(mean|zero) test coefficients for statistical significance

level(#) set confidence level for significance testing

show(show_options) add elements to the plot (see details below)

boxplot display boxplots instead of point estimates

style_m_sig(marker_options) rendition of markers, significant

style_m_nosig(marker_options) rendition of markers, non-significant

style_ci_sig(line_options) rendition of confidence intervals, significant

style_ci_nosig(line_options) rendition of confidence intervals, non-significant

style_ind_act(marker_options) rendition of indicators, active

style_ind_pas(marker_options) rendition of indicators, passive

style_l_mean(line_options) rendition of meanline, if specified via show(mean)

twoway_options twoway options, other than by()

show_options

mean adds a horizontal line at the overall mean of varname

sig contrasts significant and non-significant estimates

ci_regular adds confidence intervals to coefficients, using solid lines

ci_gradient adds confidence intervals to coefficients, using color gradients

Note: In line with Stata Tip 103 (Kohler & Eckman, 2011) users are encouraged to use color gradients to express uncertainty.
They should keep in mind, though, that this option adds many layers to the graph (~20 per group), potentially resulting in memory issues
(especially if the number of factors and levels in factors(varlist) is large).

groupsize adds case numbers to the x-axis

Description

mfcurve plots the mean of variable varname over all multifactorial combinations in factors(varlist).

The plot consists of two subgraphs: an upper panel, displaying the mean outcome per group; and a lower panel, indicating the presence/absence of each factor level.
Symbols in the upper panel are referred to as markers; symbols in the lower panel are referred to as indicators.
The graph follows the overall aesthetics of a specification curve but displays effect variation across treatment specifications instead of effect variation across model specifications.

Options

groupvar(varname) allows users to specify what variable should be used to label subgroups. By default, mfcurve is agnostic and assigns numerical IDs based on all possible combinations in factors(varlist).

test(...) tests coefficients for statistical significance using t-tests.

test(mean) performs two-sample t tests on the equality of means of varname in each group (treatment) against the pooled mean across all other groups (control).
By design, the composition of the control group depends on the choice of the treatment group, meaning the reference value to be tested against will vary across t tests.
As a result, a coefficient's confidence interval might overlap with the overall mean, i.e. displayed by show(mean), despite being significantly different from the mean in the control group, according to the t test.
Similarly, two neighboring coefficients may differ with regards to their statistical significance despite having seemingly identical confidence intervals.

test(zero) performs one-sample t tests for each group against zero.

level(#) enables users to set the confidence level for significance testing; see [R] level. Unless specified otherwise, the default value is level(95).

show(...) lets users add visual elements to the plot (see show_options above).

boxplot replaces point estimates with boxplots (see Cox, 2009). This option may only be specified if varname is polytomous and cannot be combined with test(...) and show(...).

style_m_sig(marker_options) enables users to manipulate the rendition of significant markers.

style_m_nosig(marker_options) enables users to manipulate the rendition of non-significant markers.

style_ci_sig(line_options) enables users to manipulate the rendition of significant confidence intervals.

Note: If show(ci_gradient) is used, the CI's color needs to be determined using color(colorstyle) instead of lcolor(colorstyle).

style_ci_nosig(line_options) enables users to manipulate the rendition of non-significant confidence intervals.

Note: If show(ci_gradient) is used, the CI's color needs to be determined using color(colorstyle) instead of lcolor(colorstyle).

style_ind_act(marker_options) enables users to manipulate the rendition of active indicators.

style_ind_pas(marker_options) enables users to manipulate the rendition of passive indicators.

style_l_mean(line_options) enables users to manipulate the rendition of the meanline, if specified via show(mean).

Stored results

Matrix

r(testresults) if option test(...) has been specified, the matrix contains the details of the t tests (i.e. means, standard deviations, sample sizes, confidence intervals, p-values, etc.) for all groups.

Examples

mfcurve may, for instance, be used descriptively to plot the average income across distinct groups defined by race, region, and union membership:

. sysuse nlsw88, clear
. drop if missing(race, south, union, wage)
. mfcurve wage, factors(race south union)

In the graph, higher hourly wages seem to be associated with union membership and not living in the south. To assess if this is due to small cell sizes in certain subgroups, we can type:

. mfcurve wage, factors(race south union) show(groupsize)

Indeed, there are very few observations with race == "other" (groups 9-11), so we might want to drop these. We then test if the income of each remaining group differs significantly (at the 99% level) from the mean income across all other groups:

. drop if race == 3
. mfcurve wage, factors(race south union) show(sig) test(mean) level(99)

To convey more information, we might want to add the overall mean and display confidence intervals:

mfcurve wage, factors(race south union) show(sig mean ci_regular) test(mean) level(99)

The ylabels in the graph's lower panel are based on the variables in factors(...). We can rename/relabel those variables to improve the graph's appearance.

. rename race Race
. rename south Region
. label define region_lbl 0"North" 1"South"
. label values Region region_lbl
. rename union Union
. label define union_lbl 0"No" 1"Yes"
. label values Union union_lbl

. mfcurve wage, factors(Race Region Union) show(sig mean ci_regular) test(mean) level(99)

Finally, we obtain a full-fledged mfcurve using color gradients to express uncertainty in estimates,
removing the automatically generated (and here: meaningless) group identifiers on the x-axis,
customizing the marker symbols, and specifying a few general twoway_options. Note that due to the option show(ci_gradient) the graph will take a few seconds to compile.

. local twoptions xlab(none) ylab(5(1)11) ytitle("Hourly Wage (in US$)") xtitle("") graphregion(color(white))
. mfcurve wage, factors(Race Region Union) show(sig mean ci_gradient) test(mean) level(99) style_m_sig(msymbol(D)) `twoptions'

References

Kohler, Ulrich, and Stephanie Eckman. 2011. "Stata Tip 103: Expressing Confidence with Gradations." The Stata Journal 11(4):627–31. doi: 10.1177/1536867X1201100409.

Cox, Nicholas J. 2009. "Speaking Stata: Creating and Varying Box Plots." The Stata Journal: Promoting Communications on Statistics and Stata 9(3):478–96. doi: 10.1177/1536867X0900900309.

Acknowledgements

This ado has drawn inspiration from the Stata ado speccurve, authored by Hans H. Sievertsen. Thanks to my colleagues at the Department of Sociology at LMU Munich for their helpful comments and suggestions.

Author Details

Daniel Krähmer, Ludwig-Maximilans-Universität (LMU) Munich

Contact: daniel.kraehmer@soziologie.uni-muenchen.de