By default, coefplot displays the results as they have been stored by
the estimation command in e(b). These raw coefficients may not
always be what you want to see. For example, in case of a
logit model,
you may want to use the
eform option to
transform the raw log odds to odds ratios:
. sysuse auto, clear (1978 automobile data) . logit foreign mpg trunk length turn (output omitted) . coefplot, drop(_cons) xline(1) eform xtitle(Odds ratio)Code
Similarly, eform
computes hazard ratios after
stcox,
relative-risk ratios after
mlogit,
or incidence-rate ratios after
poisson.
You can also transform just a selection of coefficients; see
eform()
in the help file.
The
rescale()
option allows you to rescale the estimates by a multiplicative factor.
For example, to plot percentages instead of fractions after
proportion,
type:
. sysuse auto, clear (1978 automobile data) . proportion rep78 Proportion estimation Number of obs = 69 -------------------------------------------------------------- | Logit | Proportion Std. err. [95% conf. interval] -------------+------------------------------------------------ rep78 | 1 | .0289855 .0201966 .0070794 .1110924 2 | .115942 .0385422 .058317 .2173648 3 | .4347826 .0596787 .3214848 .5553295 4 | .2608696 .0528625 .1695907 .3788629 5 | .1594203 .0440694 .0895793 .267702 -------------------------------------------------------------- . coefplot, rescale(100) xtitle(Percent) recast(bar) barwidth(0.5) finten(60) /// > citop citype(logit) ciopt(recast(rcap))Code
Note that option citype(logit) was
specified to compute the confidence limits using a logit transformation, as
this is the default method used by
proportion.
You can also rescale single coefficients, as in the following example:
. sysuse auto, clear (1978 automobile data) . generate gpm = 1 / mpg . regress price weight gpm turn Source | SS df MS Number of obs = 74 -------------+---------------------------------- F(3, 70) = 18.28 Model | 279009499 3 93003166.4 Prob > F = 0.0000 Residual | 356055897 70 5086512.81 R-squared = 0.4393 -------------+---------------------------------- Adj R-squared = 0.4153 Total | 635065396 73 8699525.97 Root MSE = 2255.3 ------------------------------------------------------------------------------ price | Coefficient Std. err. t P>|t| [95% conf. interval] -------------+---------------------------------------------------------------- weight | 2.480716 .8380717 2.96 0.004 .8092351 4.152198 gpm | 110541.8 39814.31 2.78 0.007 31134.71 189949 turn | -410.4216 116.9504 -3.51 0.001 -643.6719 -177.1713 _cons | 9399.092 3101.64 3.03 0.003 3213.066 15585.12 ------------------------------------------------------------------------------ . coefplot, drop(_cons) xline(0) rescale(weight = 100 gpm = .01) /// > coeflabels(weight = "Weight (in 100 lbs.)" gpm = "Gallon per 100 miles")Code
Or here is an example in which the effects are rescaled by the standard deviations of the predictors (semi-standardized effects):
. sysuse auto, clear (1978 automobile data) . regress price mpg weight length turn (output omitted) . foreach v of var mpg weight length turn { 2. quietly summarize `v' 3. local sd_`v' = r(sd) 4. } . coefplot, drop(_cons) xline(0) /// > rescale(mpg = `sd_mpg' /// > weight = `sd_weight' /// > length = `sd_length' /// > turn = `sd_turn')Code
More generally, you can use the
transform()
option to apply arbitrary transformations (using endpoint transformation
for confidence limits). Within the expressions in
transform(), use
@ as a placeholder for the value to be transformed. For example,
transform(* = exp(@))
does the same as the eform
option discussed above:
. sysuse auto, clear (1978 automobile data) . logit foreign mpg trunk length turn (output omitted) . coefplot (., eform label(eform)) /// > (., transform(* = exp(@)) label(transform)) /// > , drop(_cons) xline(1) xtitle(Odds ratio)Code
Likewise, to plot standard deviations and correlations of
random effects after a mixed-effects model
(mixed),
type:
. webuse pig, clear (Longitudinal analysis of pig weights) . mixed weight week || id: week, covariance(unstructured) Performing EM optimization ... Performing gradient-based optimization: Iteration 0: log likelihood = -868.96185 Iteration 1: log likelihood = -868.96185 Computing standard errors ... Mixed-effects ML regression Number of obs = 432 Group variable: id Number of groups = 48 Obs per group: min = 9 avg = 9.0 max = 9 Wald chi2(1) = 4649.17 Log likelihood = -868.96185 Prob > chi2 = 0.0000 ------------------------------------------------------------------------------ weight | Coefficient Std. err. z P>|z| [95% conf. interval] -------------+---------------------------------------------------------------- week | 6.209896 .0910745 68.18 0.000 6.031393 6.388399 _cons | 19.35561 .3996387 48.43 0.000 18.57234 20.13889 ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ Random-effects parameters | Estimate Std. err. [95% conf. interval] -----------------------------+------------------------------------------------ id: Unstructured | var(week) | .3715251 .0812958 .2419532 .570486 var(_cons) | 6.823363 1.566194 4.351297 10.69986 cov(week,_cons) | -.0984378 .2545767 -.5973991 .4005234 -----------------------------+------------------------------------------------ var(Residual) | 1.596829 .123198 1.372735 1.857505 ------------------------------------------------------------------------------ LR test vs. linear model: chi2(3) = 764.58 Prob > chi2 = 0.0000 Note: LR test is conservative and provided only for reference. . coefplot, noeqlabels keep(ln*: at*:) /// > transform(ln*: = exp(@) at*: = tanh(@)) /// > coeflabels(ln*1: = "se(week)" ln*2: = "se(_cons)" /// > at*: = "corr(week,_cons)" ln*e: = "sd(Residual)")Code
Note that
eform,
rescale(),
and transform()
operate independently from each other. If all three are specified,
eform
is applied first, then
rescale(), then
transform().
There are a number of
temporary variables
you can refer to within the
transform()
option. Here is an example in which the lower and upper parts of the
confidence intervals are displayed in different colors:
. sysuse auto, clear (1978 automobile data) . regress price ibn.rep78, nocons (output omitted) . coefplot (., cionly transform(* = min(@,@b)) pstyle(p2)) /// > (., cionly transform(* = max(@,@b)) pstyle(p3)) /// > (., noci pstyle(p1)) /// > , nooffsets ciopts(lwidth(*10) lcolor(*.5)) legend(off)Code
The keep()
and drop()
options determine the equations and
coefficients that will be included in the graph based on their names (see
the examples in Getting started). Sometimes,
however, it is useful to select coefficients based on their values. In
this case, the if()
option can be employed. For example, suppose you
want to use a different plot style for significant and nonsignificant
coefficients. You could type:
. sysuse auto, clear (1978 automobile data) . regress price mpg trunk length turn if foreign==1 (output omitted) . coefplot (., if(@ll<0 & @ul>0)) /// nonsignificant (0 included in CI) > (., if(@ll>0 | @ul<0)) /// significant (0 not in CI) > , drop(_cons) nooffset xline(0) legend(off)Code
@ll and @ul are internal variables
containing the lower and upper limits of confidence intervals (see
here).
coefplot does not support standardizing coefficients. If you want to plot standardized coefficients, you have to compute the standardized coefficients before applying coefplot. An approach that works for linear regression is to standardize all variables before estimating the model, as in the following example:
. sysuse auto, clear (1978 automobile data) . preserve . center price mpg weight length turn foreign, inplace standardize (modified variables: price mpg weight length turn foreign) . regress price mpg weight length turn, noconstant (output omitted) . restore . coefplot, xline(0) xtitle(Standardized Coefficients)Code
Command center
from the SSC Archive
has been used to standardize the variables (type ssc install
center to install the command). When standardizing the variables,
make sure to use the same set of observations as are used in the model. The
noconstant option has been added to the regression command,
because the constant is zero by construction in the standardized model.
Another approach is to use
sem to estimate the model,
which stores standardized coefficients and variances in
e(b_std) and e(V_std) (results for the
confidence intervals will be
slightly different). In coefplot, use options
b() and
v()
to refer to these results:
. sysuse auto, clear (1978 automobile data) . sem (price <- mpg weight length turn) Endogenous variables Observed: price Exogenous variables Observed: mpg weight length turn Fitting target model: Iteration 0: log likelihood = -1879.0685 Iteration 1: log likelihood = -1879.0685 Structural equation model Number of obs = 74 Estimation method: ml Log likelihood = -1879.0685 ------------------------------------------------------------------------------ | OIM | Coefficient std. err. z P>|z| [95% conf. interval] -------------+---------------------------------------------------------------- Structural | price | mpg | -94.65136 78.09846 -1.21 0.226 -247.7215 58.41881 weight | 5.029726 1.114147 4.51 0.000 2.846039 7.213414 length | -73.14738 38.82984 -1.88 0.060 -149.2525 2.957707 turn | -323.8606 122.5203 -2.64 0.008 -563.996 -83.72509 _cons | 19581.42 5798.795 3.38 0.001 8215.988 30946.85 -------------+---------------------------------------------------------------- var(e.price)| 5039170 828434.4 3651088 6954977 ------------------------------------------------------------------------------ LR test of model vs. saturated: chi2(0) = 0.00 Prob > chi2 = . . coefplot, drop(_cons) xline(0) b(b_std) v(V_std) /// > xtitle(Standardized Coefficients)Code
Yet another solution is to manually specify scaling factors for the
different coefficients using the
rescale()
option (see above).
coefplot can plot results computed by
margins
if it is specified with the post option.
For example, if you want to plot average marginal effects instead of log odds or
odds ratios from a logit
model, you can apply margins
as follows:
. sysuse auto, clear (1978 automobile data) . logit foreign mpg trunk length turn (output omitted) . margins, dydx(*) post Average marginal effects Number of obs = 74 Model VCE: OIM Expression: Pr(foreign), predict() dy/dx wrt: mpg trunk length turn ------------------------------------------------------------------------------ | Delta-method | dy/dx std. err. z P>|z| [95% conf. interval] -------------+---------------------------------------------------------------- mpg | -.0132652 .008305 -1.60 0.110 -.0295426 .0030122 trunk | -.000315 .0126011 -0.02 0.980 -.0250128 .0243828 length | -.0047259 .0041489 -1.14 0.255 -.0128577 .0034059 turn | -.0526197 .0148773 -3.54 0.000 -.0817788 -.0234607 ------------------------------------------------------------------------------ . coefplot, xline(0) xtitle(Average maginal effects)Code
It is essential to specify the post option with
margins so
that it posts its results in e() from where coefplot collects
the results to be displayed. If you do not specify the post option,
then margins
leaves e() unchanged and coefplot uses
the raw coefficients from the
logit
model that still reside in e().
Here is an example for plotting average marginal effects for all equations
of an mlogit.
The code is a bit involved because
margins
has a complicated way of naming things:
. webuse sysdsn1, clear (Health insurance data) . mlogit insure i.male i.nonwhite i.site (output omitted) . margins, dydx(*) post Average marginal effects Number of obs = 616 Model VCE: OIM dy/dx wrt: 1.male 1.nonwhite 2.site 3.site 1._predict: Pr(insure==Indemnity), predict(pr outcome(1)) 2._predict: Pr(insure==Prepaid), predict(pr outcome(2)) 3._predict: Pr(insure==Uninsure), predict(pr outcome(3)) ------------------------------------------------------------------------------ | Delta-method | dy/dx std. err. z P>|z| [95% conf. interval] -------------+---------------------------------------------------------------- 0.male | (base outcome) -------------+---------------------------------------------------------------- 1.male | _predict | 1 | -.1222033 .0452073 -2.70 0.007 -.210808 -.0335985 2 | .1106393 .0456373 2.42 0.015 .0211918 .2000869 3 | .0115639 .0247844 0.47 0.641 -.0370126 .0601405 -------------+---------------------------------------------------------------- 0.nonwhite | (base outcome) -------------+---------------------------------------------------------------- 1.nonwhite | _predict | 1 | -.2001526 .0485656 -4.12 0.000 -.2953394 -.1049658 2 | .2189894 .0497992 4.40 0.000 .1213847 .3165941 3 | -.0188368 .0230976 -0.82 0.415 -.0641073 .0264337 -------------+---------------------------------------------------------------- 1.site | (base outcome) -------------+---------------------------------------------------------------- 2.site | _predict | 1 | .0009568 .0479225 0.02 0.984 -.0929696 .0948833 2 | .0667526 .0480807 1.39 0.165 -.0274839 .1609891 3 | -.0677094 .023939 -2.83 0.005 -.114629 -.0207898 -------------+---------------------------------------------------------------- 3.site | _predict | 1 | .114833 .0506483 2.27 0.023 .0155641 .214102 2 | -.120154 .0491288 -2.45 0.014 -.2164447 -.0238633 3 | .005321 .0312838 0.17 0.865 -.0559941 .066636 ------------------------------------------------------------------------------ Note: dy/dx for factor levels is the discrete change from the base level. . coefplot (, keep(*:1._predict) label(Indemnity)) /// > (, keep(*:2._predict) label(Prepaid)) /// > (, keep(*:3._predict) label(Uninsure)) /// > , swapnames xline(0) legend(rows(1))Code
In Stata 13 or older, margins
did not support computing marginal effects for all equations in one run. Here is an
example that shows you how to compute the results by looping over the outcomes:
. webuse sysdsn1, clear (Health insurance data) . mlogit insure i.male i.nonwhite i.site (output omitted) . estimates store mlogit . forvalues o = 1/3 { 2. local oname: word `o' of Indemnity Prepaid Uninsure 3. quietly margins, dydx(*) post predict(outcome(`o')) 4. estimates store `oname' 5. quietly estimates restore mlogit 6. } . coefplot Indemnity Prepaid Uninsure, xline(0) legend(rows(1))Code