Skip to main content
← Back to Software

eplot

Graphics

Forest and coefficient plots from any source

. net install eplot, from(...)
View on GitHub →

eplot hex logo

Version 1.0.0 | 2026-10-26

[version Stata 16+ MIT license Part of Stata-Tools

Quick Start · Installation · Key Options · Gallery · Stata-Tools · Report a bug

eplot creates forest plots and coefficient plots from variables, estimation results, matrices, or graph-ready frames. It gives applied Stata users one plotting workflow for effect sizes, confidence intervals, model comparison, and publication-oriented annotations.

Quick Start

After installing, draw a meta-analysis forest plot with weighted boxes, prediction intervals, a values column, and direction labels from study-level results typed in as data:

clear
input str20 study double(es lci uci pi_lci pi_uci weight) byte type
"Smith 2018"   -0.42  -0.78  -0.06  -1.15   0.31  12.3  1
"Jones 2019"   -0.31  -0.58  -0.04  -1.04   0.42  16.8  1
"Brown 2020"   -0.18  -0.41   0.05  -0.91   0.55  21.5  1
"Lee 2021"     -0.55  -0.93  -0.17  -1.28   0.18  10.2  1
"Garcia 2022"  -0.27  -0.49  -0.05  -1.00   0.46  19.1  1
"Patel 2023"   -0.09  -0.35   0.17  -0.82   0.64  20.1  1
"Overall"      -0.28  -0.41  -0.15   .       .      .    5
end

eplot es lci uci, labels(study) weights(weight) type(type) ///
    values vformat(%4.2f) ///
    pi(pi_lci pi_uci) ///
    i2("42.1%") tau2("0.021") qstat("8.63, df=5, p=0.125") ///
    effect("Mean Difference (95% CI)") ///
    favors("Favors Treatment" "Favors Control")

Meta-analysis forest plot of six studies with weight-proportional boxes, dashed prediction-interval whiskers, an overall diamond, a values column of mean differences with 95% confidence intervals, Favors Treatment and Favors Control labels at the null, and a heterogeneity note

Drawn by demo/demo_eplot.do, which also sets the white_tableau scheme from the tc_schemes package and adds title("Meta-Analysis with Prediction Intervals").

For a coefficient plot of the model you just fitted, eplot . reads the active estimation results:

sysuse auto, clear
regress price mpg weight foreign
eplot ., drop(_cons) cicap

Features

  • Four inputs, one vocabulary. Variables in memory, active or stored estimates, a matrix, or a frame share one set of selection, labelling, transform, and display options; the Key Options tables mark the few that are mode-specific.
  • Meta-analysis layouts. type() marks headers, pooled subgroup and overall rows (drawn as diamonds), heterogeneity rows, and spacers; weights() sizes the boxes, pi() adds prediction-interval whiskers, and i2(), tau2(), and qstat() print heterogeneity text you supply (it is not computed).
  • Intervals that match Stata's tables. Estimates mode uses the t distribution with e(df_r), or parameter-specific degrees of freedom after mi estimate, post and mixed, dfmethod(), and eform exponentiates only the equations Stata's own eform rule covers.
  • Publication annotations. A values column with its own header, size, and format, favors() direction labels, labelled xline() reference lines, logscale axes, and journal presets through style().
  • No silent drops. A keep() or drop() name that matches nothing exits with r(198), and a data row with a missing estimate is left out with a note naming it.

Requirements

  • Stata 16 or later
  • No required external packages
  • The optional tabtools companion-frame workflow requires sibling tabtools; its regtab, effecttab, comptab, and hrcomptab commands require Stata 17 or later

Installation

Install the released package from Stata-Tools:

capture ado uninstall eplot
net install eplot, from("https://raw.githubusercontent.com/tpcopeland/Stata-Tools/main/eplot") replace

For a local Stata-Tools checkout, replace the URL with the package directory:

capture ado uninstall eplot
net install eplot, from("/path/to/Stata-Tools/eplot") replace

Commands

Command Description
eplot Draw forest and coefficient plots from data, estimates, matrices, or frames

How It Works

eplot selects an input mode from the call and then applies a shared plotting vocabulary to the resulting effects and confidence limits.

Calling convention Mode Use it when
eplot esvar lcivar ucivar [if] [in], ... Data Point estimates and confidence limits are variables in the active dataset
eplot [namelist], ... Estimates Plot active estimates with eplot . or compare stored models
eplot, matrix(matname) ... Matrix Results are assembled in a Stata matrix
eplot [if] [in], frame(framename) ... Frame A graph-ready result table is stored in a Stata frame

Mode detection checks explicit matrix() first, then frame(). With no namelist or with . it uses active estimation results; a call with three leading numeric variables selects data mode, and estimate names select estimates mode. Use an explicit selector when a variable name and stored estimate name could be confused.

Data mode uses the three variables as estimate, lower confidence limit, and upper confidence limit. Optional type() values identify headers, regular effects, pooled subgroup/overall effects, heterogeneity rows, and blank spacers. Matrix mode accepts either two columns (b, se) or three columns (b, ll, ul); all required cells must be nonmissing, and row names supply plot labels when present.

Frame mode requires numeric estimate, ll, and ul variables unless estimate(), ll(), and ul() override those names. It automatically uses string label, numeric or string rowtype or type, numeric weight or weights, and numeric pvalue variables when they are present; type() and rowtype() are mutually exclusive. Frame mode reuses the data-mode plotting options, including groups, headers, pooled rows, weights, prediction intervals, and heterogeneity notes.

The optional tabtools bridge lets regtab, effecttab, comptab, and hrcomptab produce companion frames for eplot, frame(). The repository demo documents that workflow and requires sibling tabtools and tc_schemes packages, the _data/ fixtures, and Stata 17 or later.

Worked Examples

1. Data mode: forest plot from variables

Use data mode when point estimates and confidence limits already exist in the dataset.

clear
input str20 study double es lci uci weight byte type
"Study A"  -.16  -.36   .03  15.2  1
"Study B"  -.33  -.54  -.12  18.4  1
"Study C"  -.09  -.25   .06  22.1  1
"Overall" -.24  -.34  -.13      .  5
end

eplot es lci uci, labels(study) weights(weight) type(type) values ///
    effect("Mean Difference (95% CI)")

The type-5 row is drawn as a pooled diamond, while the study rows use weight-proportional boxes.

2. Estimates mode: compare stored models

Store models in the order you want them shown, then supply their names and optional legend labels.

sysuse auto, clear
quietly regress price mpg weight foreign
estimates store base
quietly regress price mpg weight length headroom foreign
estimates store extended

eplot base extended, drop(_cons) ///
    modellabels("Base" "Extended") cicap

A single active model uses eplot .; multiple single-equation models share coefficient rows and receive separate legend entries. Multi-equation estimates retain equation prefixes when coefficient names repeat, and plotting named estimates preserves the caller’s active estimation state. Confidence intervals and p-values use the t distribution when a model provides positive residual degrees of freedom and the normal distribution otherwise, evaluated separately for each model.

3. Matrix mode: exponentiated effects with stars

A two-column matrix is interpreted as b and se, so confidence limits and p-values can be computed.

matrix R = (0.20, 0.10 \ -0.10, 0.08 \ 0.30, 0.12)
matrix rownames R = Treatment_A Treatment_B Treatment_C

eplot, matrix(R) eform values stars ///
    effect("Odds Ratio (95% CI)")

Use a three-column matrix when the second and third columns are already the lower and upper confidence limits.

4. Frame mode: plot a graph-ready frame

Frame mode can consume a custom frame directly and auto-detect its pvalue variable for stars.

clear
input str12 label double estimate ll ul pvalue byte rowtype
"Age"     1.12 1.04 1.20 0.004 1
"Sex"     0.86 0.70 1.06 0.150 1
"Overall" 1.03 0.97 1.10 0.320 5
end
frame put label estimate ll ul pvalue rowtype, into(effects)

eplot, frame(effects) values stars rowtype(rowtype) ///
    effect("Odds Ratio (95% CI)") null(1)
frame drop effects

The active dataset is restored after the frame is copied and plotted.

5. Estimates mode: eform, grouping, and style

Use eform for log-scale model output; explicit labels and groups can be layered over a journal preset.

sysuse auto, clear
logit foreign mpg weight length headroom trunk turn

eplot ., noconstant eform style(lancet) values ///
    groups(mpg weight = "Efficiency and mass" ///
           length headroom trunk turn = "Vehicle dimensions") ///
    gap(.5)

In estimates mode, eform sets the null line to 1 and suppresses _cons automatically.

6. Publication forest plot: values column, labelled reference line, and favors

Subgroup time ratios on a log axis, with the values printed at the row-label size and an extra reference line at the overall estimate (synthetic data).

clear
input str20 group double(tr lci uci) byte type
"Men"                .     .     .   0
"  18-39"         1.21  1.04  1.41   1
"  40-59"         1.09  0.97  1.22   1
"  60-79"         1.03  0.94  1.13   1
"  80+"              .     .     .   2
""                   .     .     .   6
"Women"              .     .     .   0
"  18-39"         1.34  1.16  1.55   1
"  40-59"         1.12  1.01  1.24   1
"  60-79"         0.97  0.88  1.07   1
"  80+"           0.88  0.73  1.06   1
""                   .     .     .   6
"All participants" 1.08  1.03  1.13  5
end

eplot tr lci uci, labels(group) type(type) logscale ///
    values vformat(%4.2f) vsize(small) vcolor(black) ///
    effect("Time ratio (log scale)") vtitle("Time ratio (95% CI)") ///
    xlabel(0.7 "0.7" 0.8 "0.8" 1 "1.0" 1.25 "1.25" 1.5 "1.5") ///
    xscale(lcolor(black) lwidth(medthin) fextend) ///
    xline(1.08, lcolor(gs8) lpattern(dash) label("Overall 1.08")) ///
    favors("Favors SSRI" "Favors SNRI", ends arrows)

Time-ratio forest plot by sex and age group on a log axis with a Not estimated row and a labelled reference line

The type 2 row prints Not estimated in the values column (vmissing() changes the text). effect() titles the axis while vtitle() heads the values column, and vsize(small) matches the default row-label size (labsize() sets the labels). The xline() label sits at the top of the plot (a row above the values header), favors(..., ends arrows) anchors the direction labels at the ends of the effect range, and xscale() styles the axis line without touching the range eplot computes. Because xlabel() is user-supplied, no grid is drawn unless it asks for one with xlabel(..., grid); with default ticks, nogrid removes the grid.

7. Consistent panels: shared axis styling

Keep the styling options for a multi-panel figure in one local so the panels cannot drift apart.

local shared `"logscale xlabel(0.7 "0.7" 1 "1.0" 1.4 "1.4") xscale(lcolor(black) lwidth(medthin) fextend) values vformat(%4.2f) vsize(small) vcolor(black) labsize(small) effect("Hazard ratio") vtitle("HR (95% CI)") vmissing("Too few events") favors("Favors SNRI" "Favors SSRI", below arrows)"'

* ... load panel A results (hr lci uci subgroup type) ...
eplot hr lci uci, labels(subgroup) type(type) `shared' ///
    title("A. Cardiovascular event", size(medium)) name(panel_cv, replace) nodraw

* ... load panel B results ...
eplot hr lci uci, labels(subgroup) type(type) `shared' ///
    title("B. Gastrointestinal bleeding", size(medium)) name(panel_gi, replace) nodraw

graph combine panel_cv panel_gi, cols(2) xsize(12) ysize(5)

Two side-by-side subgroup hazard-ratio panels with identical axis styling

Each panel computes its own effect-axis range from its data, so choose ticks that fall within the data of every panel. The full data for both panels are in demo/demo_eplot.do.

The ten core figures below are reproducible from a repository checkout; run demo/demo_eplot.do from the repository root to regenerate them (it draws them in the white_tableau scheme from the sibling tc_schemes package). Run demo/demo_tabtools_eplot.do to regenerate the two bridge figures; that optional integration workflow also needs sibling tabtools and tc_schemes, the repository _data/ fixtures, and Stata 17 or later. These demos are checkout workflows and are not part of the net install payload.

Output Command focus
Single-model coefficient plot with formatted estimates and capped confidence intervals values after a single regression
Crude versus adjusted treatment-effect forest plot from comptab comptab forest bridge
Adjusted odds-ratio forest plot from a regtab companion frame regtab to eplot, frame()
Grouped meta-analysis forest plot with weighted boxes and pooled diamonds type(), weights(), pooled rows, and vsize(small) values
Grouped odds-ratio coefficient plot with section headers groups() and eform
Lancet-style coefficient plot with cranberry diamonds and capped intervals style(lancet)
Odds-ratio forest plot generated from a matrix Three-column matrix() input with null(1)
Meta-analysis forest plot with prediction intervals and heterogeneity note pi(), i2(), tau2(), and qstat()
Three-model coefficient comparison with separate legend colors modellabels() and palette()
Two side-by-side subgroup hazard-ratio panels with identical axis styling Shared xlabel(), xscale(), text sizes, vmissing(), and favors(, below arrows) across panels
Coefficient plot with contrasting significant and non-significant colors sigcolors, sigcolor(), and insigncolor()
Time-ratio forest plot by sex and age group on a log axis with a Not estimated row and a labelled reference line logscale, vtitle(), vsize(), labelled xline(), and favors(, ends arrows)

Key Options

Availability tags are D = data, E = estimates, M = matrix, and F = frame. Frame mode accepts the data-mode plotting options after its frame selector. Options not marked with a mode are accepted in all four modes; additional twoway graph options are passed through.

Input and row structure

Option Modes Contract and default
matrix(matname) M Selects a two- or three-column matrix
frame(framename) F Selects a graph-ready frame
estimate(varname), ll(varname), ul(varname) F Override frame variables; defaults are estimate, ll, and ul
labels(varname) D, F String row labels; data mode defaults to Row 1, Row 2, and so on; frame mode auto-detects label
weights(varname) D, F Numeric marker/box weights; frame mode auto-detects weight, then weights. Unless nobox is specified, every plotted type-1 row must carry a nonmissing, positive weight
type(varname) D, F Row-role variable; omitted rows are regular effects
rowtype(varname) F Frame synonym for type(); auto-detected when present
pvalue(varname) D, F Numeric p-values in [0, 1] for stars and r(pvalues); frame mode auto-detects pvalue
pi(lci_var uci_var) D, F Complete, ordered prediction-limit pairs drawn as dashed whiskers behind confidence intervals

Data/frame type() values are 0 = header, 1 = regular effect, 2 = missing/excluded, 3 = subgroup pooled effect, 4 = heterogeneity row, 5 = overall pooled effect, and 6 = blank spacer. String values effect/regular, header/section, missing/reference, subgroup, hetinfo, overall, and blank are also recognized; unknown values are rejected.

Selection and labeling

Option Modes Contract and default
keep(coeflist) D, E, M, F Keep only listed names; * and ? wildcards are supported; estimates/matrix modes also match eq:name; data/frame modes match the source labels() values, including structural rows; a name or pattern that matches nothing exits with r(198)
drop(coeflist) D, E, M, F Drop listed names, matched as in keep(); a name or pattern that matches no coefficient of the model exits with r(198) (_cons, and names already removed by keep() or omitted, are exempt); selection leaving no plottable effect row is an error
rename(spec) E Rename matched estimates for display before labels/groups are applied; all mappings apply at once to the original names, so swaps and chains work
noconstant D, E, M, F Drop _cons; not an error when there is no constant
coeflabels(spec) D, E, M, F Replace matched coefficient/effect labels using well-formed mappings; applied after keep(), drop(), order(), groups(), and headers(), all of which key on the original names
groups(spec) D, E single, F Insert bold group headers; members are gathered, in display order, at the group's first member; every named effect must match, and a coefficient may belong to one group only
headers(spec) / headings(spec) D, E single, F Insert a header before a matched effect; headings() is an alias
gap(#) D, E single, F Nonmissing, nonnegative extra group spacing; default is 0

Transform, reference lines, and intervals

Option Modes Contract and default
eform D, E, M, F Exponentiate estimates and limits; the null defaults to 1 instead of 0
logscale D, E, M, F Draw the effect axis on a logarithmic scale with multiplicative padding and decade ticks; all plotted values, null(), and xline() positions must be positive, and the null defaults to 1
rescale(#) D, E, M, F Nonmissing, nonzero multiplier for estimates and limits on the estimation scale (with eform, rescale(10) plots exp(10*b)); negative factors preserve lower/upper ordering; default is 1
xline(numlist[, line_options label(strlist[, size() color() placement()])]) D, E, M, F Add reference lines; repeatable, one style per occurrence; bare positions use a light dashed style; label() gives one label per line, drawn at the top of the plot beside the line (left of it in the right half of the axis; a row above the header with values; beside the first row in vertical layout)
xlabel(spec) D, E, M, F Set effect-axis ticks in either orientation; the axis range extends to every numeric tick; draws no grid (including a scheme grid) unless its suboptions include grid
nogrid D, E, M, F Suppress the grid eplot draws with its default ticks
null(#[, line_options]) D, E, M, F Nonmissing null line position; default is 0, or 1 with eform; line options replace the dashed gray style; not drawn when off the axis
nonull D, E, M, F Suppress the null line
level(#) D, E, M, F Confidence level for constructed intervals; default is current c(level), normally 95; in data/frame mode it only labels the default title, which reads 95 without it
noci D, E, M, F Suppress all interval geometry: whiskers are omitted and data/frame pooled rows are drawn as markers rather than diamonds; the axis ranges on the point estimates
cicap D, E, M, F Use capped rcap intervals instead of rspike

Display, significance, and meta-analysis

Option Modes Contract and default
dp(#) D, E, M, F Nonnegative decimal places for values; default is 2
effect(string[, atnull]) D, E, M, F Effect-axis title, and the values header unless vtitle() is set; atnull centres the title under the null on its own row (size and color from xtitle()); data/frame default to Estimate (95% CI) or Effect (95% CI) with eform, while estimates/matrix use the current CI level
values D, E single, M, F Annotate rows with estimate and interval text; requires horizontal layout
vformat(fmt) D, E, M, F Numeric values format; default is %24.2f, or %w.dpf with w = dp + 22; fixed formats round half away from zero on the decimal value, never print -0.00, and show a row in exponent notation when any of its numbers is too wide
vsize(textsizestyle), vcolor(colorstyle) D, E single, M, F values text size and color; defaults are vsmall and gs4; vsize(small) matches the row labels
vtitle(string) D, E single, M, F Header above the values column; default is the effect() text
vgap(#) D, E single, M, F Nonmissing, nonnegative gap between the effect axis and the values column, as a fraction of the axis span (of its log span under logscale); default is 0.15. The column starts right of the widest interval, the null line when drawn, and the last labelled tick
vmissing(string) D, F values text on type 2 (missing/excluded) rows; default is Not estimated; vmissing("") leaves them blank; string reference rows stay blank
baselevels, vreference(string) E single Show factor base levels as reference rows (no marker); values text 1.00 (reference) with eform, 0.00 (reference) otherwise, or vreference(); not in r(k)/r(table)
labsize(textsizestyle) D, E, M, F Row-label size; default is small
stars D, E single, M 2-column, F Append p-value stars to values; data mode requires pvalue(), while frame mode uses pvalue() or an auto-detected pvalue variable
sigcolors D, E single, M, F Color single-model effects by whether the interval excludes null(); multi-model estimates use palette() colors
sigcolor(color) D, E single, M, F Significant-effect color when sigcolors is set; default is cranberry
insigncolor(color) D, E single, M, F Non-significant-effect color when sigcolors is set; default is gs10
favors(left right[, ends below arrows size() color() gap()]) D, E, M, F Directional labels for a horizontal effect axis, anchored at the null and reading outward from it (gap() sets the gap, default 1.5), in the tick-label size; ends at the axis ends, below under the tick labels, arrows adds direction arrows, size()/color() style the text; a null not strictly inside the tick span moves the labels to the ends
i2(string), tau2(string), qstat(string) D, F Add supplied heterogeneity text as-is to the graph note; values are not computed
hetrow D, F Show the heterogeneity text as a row (I² = …, τ² = …, Q = …) under the last overall row instead of in the note
style(name) D, E, M, F Presets: forest, coef, lancet, jama, nejm, and bmj; explicit options override preset defaults

Layout and model comparison

Option Modes Contract and default
horizontal / vertical D, E, M, F Horizontal is the default; the two orientations are mutually exclusive
sort D, E, M, F Sort regular effects by estimate within their block (between header, pooled, and blank rows, and within each groups() list); global without such rows; may not be combined with order()
order(coeflist) D, E, M, F Explicit order; unlisted rows follow in their original order; a name that matches nothing exits with r(198); may not be combined with sort
modellabels(strlist) E multi Exactly one legend label per model
offset(#) E multi Nonmissing, nonnegative vertical model spacing; default is 0.15, reduced with more than five models so a coefficient's models span at most 0.6 rows
palette(colorlist) E multi Exactly one color per model; the default palette navy cranberry forest_green dkorange purple teal maroon olive_teal cycles for a ninth model onward
legendopts(string) E multi Additional legend options; default is rows(1) pos(6) size(small)

Markers and graph options

Option Modes Contract and default
mcolor(color) D, E, M, F Marker color; default is navy in single-model plots, while multi-model estimates use palette() colors
msymbol(symbol) D, E, M, F Marker symbol (any symbolstyle, case-sensitive); default is O. An unknown name, or a list outside multi-model estimates mode, exits with r(198). With multiple models, one symbol for every model or exactly one per model, e.g. msymbol(O D T), so models differ by shape as well as color
msize(size) D, E, M, F Marker size; default is medium, or medsmall for multi-model estimates
boxscale(#) D, F Nonmissing, positive weighted-box scaling; default is 100 percent
nobox D, F Replace weight-proportional squares with standard markers
nodiamonds D, F Replace pooled-effect diamonds with standard markers
diamondcolor(overall [subgroup]) D, F Diamond outline colors; default black and maroon
cicolor(color) D, E, M, F CI line color; default follows mcolor() in single-model plots, while multi-model estimates use palette() colors
ciwidth(lwstyle) D, E, M, F CI line width; default is medium
title(string), subtitle(string), note(string) D, E, M, F Graph title, subtitle, and note
name(string), saving(filename), scheme(schemename) D, E, M, F Graph name, saved graph path, and scheme
plotregion(options), graphregion(options), aspect(#) D, E, M, F Standard Stata graph-region and aspect options; with values, plotregion() is merged with the values-column margin
export(frame[, replace]) D, E, M, F Write the plotted rows (label, estimate, ll, ul, pos, and type, weight, model_id, pvalue, values where available) to a frame that eplot, frame() reads back; the values are as plotted, so add null(1) (and logscale) after eform
xscale(), yscale() D, E, M, F Axis style suboptions such as lcolor(), lwidth(), fextend, line are merged into the axes eplot builds; range(), log, nolog, reverse, noreverse, and axis() exit with r(198)
twoway options D, E, M, F Other options are appended to the generated twoway command

Stored Results

After a successful call, eplot returns r-class results. Use return list and matrix list r(table) to inspect them.

Result Type Meaning
r(N) Scalar Number of display rows: effect rows plus generated groups()/headers() header rows, gap() spacer rows, baselevels reference rows, and the hetrow row; in data and frame modes, non-effect rows retained through type() are also included
r(k) Scalar Number of regular plotted effects; pooled rows and headers are excluded where applicable
r(n_models) Scalar Number of models in estimates mode; not returned for other modes
r(cmd) Local macro Full generated twoway command
r(table) Matrix b, ll, and ul columns; multi-model estimates use b_1 ll_1 ul_1 ...
r(pvalues) Matrix P-values when supplied in data/frame mode, available for one-model estimates, or requested for a two-column matrix with stars

For a single estimates model or a matrix, r(table) is k × 3. For multiple estimates it is k × (3 × number of models), with three columns per model. Data- and frame-mode pooled subgroup and overall rows appear in r(table) even though r(k) counts regular type-1 rows. Returned matrices use plotted labels as row names when Stata permits them; otherwise they fall back to row1, row2, and so on without truncating the graph labels.

Assumptions and Limits

  • Data and frame modes take confidence limits from supplied variables; level() is only for intervals constructed in estimates and matrix modes.
  • In data and frame modes an effect row needs an estimate and both limits. A row with no estimate, or with neither limit, is left out of the plot with a note naming it; give it type() code 2 to keep it as a labelled row. A row with exactly one missing limit exits with r(198).
  • Estimates-mode intervals and p-values use the t distribution with e(df_r), or with parameter-specific degrees of freedom when the estimator posts them (e(df_mi) after mi estimate, post; e(df) after mixed, dfmethod()), and the normal distribution otherwise. Parameters in the / equation and the variance components of mixed (its equations after the first e(k_f) fixed-effect coefficients) are omitted with a note. Omitted and base-level terms (exactly zero variance) are not plotted.
  • Supplied lower confidence limits may not exceed upper limits; prediction limits must be complete ordered pairs; two-column matrix standard errors must be nonnegative; and all required matrix cells must be nonmissing.
  • Data/frame effect titles therefore default to 95% CI wording; estimates/matrix titles use the current c(level), and single-model estimates-mode eform labels the axis with the name the command's own table gives the exponentiated column (odds, hazard, time, risk, and relative-risk ratios, IRR, SHR), falling back to "Effect" where Stata's table reads exp(b).
  • Matrix mode requires exactly two columns (b, se) or three columns (b, ll, ul); two-column input is the only matrix form that supports stars.
  • values and favors() require horizontal layout; values, stars, sigcolors, sigcolor(), and insigncolor() are single-model-only in estimates mode, and a multi-model call that explicitly supplies them exits with r(198).
  • groups(), headers(), and gap() apply to data/frame mode and single-model estimates; multi-model-only options (modellabels(), offset(), palette(), and legendopts()) require multiple estimates.
  • eform exponentiates supplied values, sets the null to 1, and suppresses _cons automatically in estimates and matrix modes.
  • logscale requires strictly positive values; a non-positive plotted value, null(), or xline() position exits with r(198) rather than drawing a collapsed axis. Ticks sit on a decade lattice (for example 0.5 1 2 5 10 20); a range wider than twelve decades labels every kth decade, at most twelve ticks, and a range narrower than threefold that contains the null gets ticks null·r^k (for the smallest r of 1.1, 1.25, 1.5, and 2 giving 4 to 9 ticks), symmetric about the null.
  • eplot computes each axis range itself. xscale() and yscale() accept style suboptions only; range(), log, reverse, axis(), and their negations exit with r(198). Use logscale for a logarithmic effect axis.
  • In data mode, three leading numeric variables win mode detection even if their names also match stored estimates; use eplot ., matrix(), or frame() to disambiguate.
  • In multi-model estimates, models are told apart by color unless msymbol() gives each its own symbol; for greyscale print or color-vision-deficient readers, pass one symbol per model. palette() sets per-model colors by default. mcolor() and cicolor() each take one color for every model or exactly one color per model (quote RGB triplets in a list); mcolor() may not be combined with palette(), and sigcolors is single-model-only. A style() preset's colors yield to the palette. The default palette cycles for a ninth model onward, so model m uses color mod(m-1, 8) + 1.
  • Style presets supply defaults only; explicitly supplied options take precedence, and a preset's values component applies only where values itself does.
  • keep(), drop(), order(), groups(), and headers() key on the original coefficient or labels() values in every mode; coeflabels() is applied last, so relabeling and grouping compose.

References

Estimates mode follows the rules in these Stata manual entries:

  • StataCorp. [P] ereturn — Post the estimation results. Stata Programming Reference Manual. t statistics with e(df_r) degrees of freedom when it is posted, normal statistics otherwise.
  • StataCorp. [ME] mixed — Multilevel mixed-effects linear regression. Stata Multilevel Mixed-Effects Reference Manual. Parameter-specific e(df) after dfmethod(), and e(V_df) after dfmethod(kroger).
  • StataCorp. [MI] mi estimate — Estimation using multiple imputations. Stata Multiple-Imputation Reference Manual. Parameter-specific e(df_mi); e(b) and e(V) are stored only with post.
  • StataCorp. [R] ml — Maximum likelihood estimation, options for use with ml display. Stata Base Reference Manual. eform exponentiates only the first e(k_eform) equations, by default the first.

Related commands:

  • coefplot by Ben Jann — a comprehensive coefficient-plot command available from SSC
  • metan — a user-written meta-analysis command available from SSC
  • meta forestplot — the official meta-analysis forest-plot command

QA

QA suites and how to run them are documented in qa/README.md.

Author

Timothy P Copeland, Karolinska Institutet

Questions and bug reports: GitHub issues. Please include the first line of which eplot and your Stata version.

To cite: Copeland TP. eplot: Forest and coefficient plots from any source. Stata-Tools, https://github.com/tpcopeland/Stata-Tools/tree/main/eplot. Please give the version you used (which eplot prints it).

License

MIT (see LICENSE)