Example III
Coefplot with matrices
As discussed before, you can also use coefplot to display values stored in matrices - these could stem from different regressions, but could also hold any other type of data. This section provides a do-file with examples how you can display such values. Next to the examples shown in the pdf, you will find an example for annotating significance stars in the do-file and the code below.
Examples
Do-file
Generating matrices from the (e)return list
We will start with the easy way to plot data from matrices with coefplot. For this, we make use of the fact that the regress and the mean command store the results in the return list, namely in the matrix r(table). This matrix already has column (and row) names, which are used by the coefplot command to automatically retrieve coefficient names. In this example, we will use the "mean" command for simplicity, but all steps the same when using the "regress" command - the only difference is how the columns are named.
Please make sure you went through the previous sections on coefplot, as we will use code from these examples.
Let's start with a quick demonstration of the matrices we work with:
clear all
sysuse auto.dta
version 16
local n = 1
foreach v of varlist rep78 headroom gear_ratio {
// run the mean (or regress) command
qui mean `v', over(foreign)
// store the r(table) results in a new matrix
// here, we only store the coefficient and the CIs, but you can also store all
mat m_`n' = r(table)[1,1...] \ r(table)[5,1...] \ r(table)[6,1...]
// this is just a demonstration; display the stored matrix
mat list m_`n'
local n = `n'+1
}
Now, we can start with the different ways to create a coefplot from matrices.
The next two examples are similar to the option 2a in the former section.
** Label/define outcomes automatically & place labels to the left **
// Using the groups option
version 16
local mlist
local glist
foreach v of varlist rep78 headroom gear_ratio {
// get the label
local lab: var la `v'
// as before, run mean/regress command
qui mean `v', over(foreign)
// as before, store the matrix
mat m_`v' = r(table)[1,1...] \ r(table)[5,1...] \ r(table)[6,1...]
// collect all matrices in a list
// ci((2 3)) denotes that the CIs are in rows 2 and 3
// --> change this to 5 6 if you work with the complete r(table)
local mlist `mlist' (mat(m_`v'), ci((2 3)))
// collect all names in a list (cf. last section)
local glist `glist' *`v'*=`"`lab'"'
}
coefplot `mlist', recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*0.foreign="Domestic" *1.foreign="Foreign") nokey ///
groups(`glist', angle(horizontal))
// Using the eqstrict & asequation options
version 16
local mlist
local glist
foreach v of varlist rep78 headroom gear_ratio {
local lab: var la `v'
qui mean `v', over(foreign)
mat m_`v' = r(table)[1,1...] \ r(table)[5,1...] \ r(table)[6,1...]
local mlist `mlist' (mat(m_`v'), ci((2 3)))
local glist `"`glist' "`lab'""'
}
coefplot `mlist', recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*0.foreign="Domestic" *1.foreign="Foreign") nokey ///
eqstrict aseq eqlab(`glist', angle(horizontal))
Generalization to any matrices
/*
What if names are not automatically set? What if you have less structured data?
Imagine you have different points you would like to plot:
Three outcomes for two groups. They are stored in the following matrices:
*/
mat A = 3
mat B = 3.2
mat C = 1.4
mat D = 1.3
mat E = 2
mat F = 2.1
/*
The coefplot command searches the matrices for column or row names to name the
coefficients. You can use this feature and make your life easier by naming the
columns (or rows) according to a pattern, e.g. outcome_group
*/
mat colnames A = "m1_a"
mat colnames B = "m1_b"
mat colnames C = "m2_a"
mat colnames D = "m2_b"
mat colnames E = "m3_a"
mat colnames F = "m3_b"
/*
Now, we have different options to display the results:
*/
// Option 1a: One color for each coefficient, ordered with "groups"
coefplot (mat(A)) (mat(B)) (mat(C)) (mat(D)) (mat(E)) (mat(F)), ///
recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*_a = "Group A" *_b = "Group B") ///
groups(m1_*="Outcome 1" m2_*="Outcome 2" m3_*="Outcome 3") ///
nokey xlab(0(0.5)3.5) name(g1, replace)
// Option 1b: One color for each coefficient, ordered with "headings"
coefplot (mat(A)) (mat(B)) (mat(C)) (mat(D)) (mat(E)) (mat(F)), ///
recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*_a = "Group A" *_b = "Group B") ///
headings(m1_a="Outcome 1" m2_a="Outcome 2" m3_a="Outcome 3") ///
nokey xlab(0(0.5)3.5) name(g1_1, replace)
// Option 2a: One color for each outcome, ordered with "groups"
coefplot (mat(A) \ mat(B)) (mat(C) \ mat(D)) (mat(E) \ mat(F)), ///
recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*_a = "Group A" *_b = "Group B") ///
groups(m1_*="Outcome 1" m2_*="Outcome 2" m3_*="Outcome 3") ///
nokey xlab(0(0.5)3.5) name(g2, replace)
// Option 2b: One color for each outcome, ordered with "headings"
coefplot (mat(A) \ mat(B)) (mat(C) \ mat(D)) (mat(E) \ mat(F)), ///
recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*_a = "Group A" *_b = "Group B") ///
headings(m1_a="Outcome 1" m2_a="Outcome 2" m3_a="Outcome 3") ///
nokey xlab(0(0.5)3.5) name(g2_1, replace)
// Option 3a: One color for each outcome, legend
coefplot (mat(A) \ mat(B)) (mat(C) \ mat(D)) (mat(E) \ mat(F)), ///
recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*_a = "Group A" *_b = "Group B") ///
plotlabels("Outcome 1" "Outcome 2" "Outcome 3") ///
xlab(0(0.5)3.5) name(g3, replace)
// Option 3b: One color for each outcome, legend and gaps
coefplot (mat(A) \ mat(B)) (mat(C) \ mat(D)) (mat(E) \ mat(F)), ///
recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*_a = "Group A" *_b = "Group B") ///
plotlabels("Outcome 1" "Outcome 2" "Outcome 3") ///
xlab(0(0.5)3.5) name(g3_1, replace) order(m1* . m2* .)
// Option 4: One color for each group
coefplot (mat(A)) (mat(B)) (mat(C)) (mat(D)) (mat(E)) (mat(F)), ///
recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
legend(order(1 3) lab(1 "Group A") lab(3 "Group B")) ///
groups(m1_*="Outcome 1" m2_*="Outcome 2" m3_*="Outcome 3") ///
ylab(none) xlab(0(0.5)3.5) pcycle(2) name(g4, replace)
Please note the following:
- The following options are just for the optics and the same across graphs, you might as well leave them out: recast(bar) citop fint(*.75) graphr(c(white)) nooffset xlab(0(0.5)3.5)
- The "coeflab" option uses the fact that we gave the matrices systematic colnames: All values from group A end with _a, all values from group B _b. Therefore, we can label all coefficients from one group at once. The same logic applies to the "groups" option for the different outcomes. Please note that this is slightly different for the "headings" option, as we only want a heading above the first value for each outcome, not above every value.
- When we type (mat(A)) (mat(B)) we refer to matrices A and B as two different "plots", to which different plotoptions may apply. When we type (mat(A) \ mat(B)) we refer to matrices A and B as two different "models" within the same "plot", to which the same plotoptions, but different modeloptions may apply. For more, check out the top of the coefplot help-file
/*
Alternatively, we can merge the matrices, such that we have one per outcome.
Note that this is similar to putting them in one plot group above.
*/
mat V1 = A , B
mat V2 = C , D
mat V3 = E , F
coefplot (mat(V1)) (mat(V2)) (mat(V3)), ///
recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*_a = "Group A" *_b = "Group B") ///
groups(m1_*="Outcome 1" m2_*="Outcome 2" m3_*="Outcome 3") ///
nokey xlab(0(0.5)3.5) name(g5, replace)
coefplot (mat(V1)) (mat(V2)) (mat(V3)), ///
recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*_a = "Group A" *_b = "Group B") ///
headings(m1_a="Outcome 1" m2_a="Outcome 2" m3_a="Outcome 3") ///
nokey xlab(0(0.5)3.5) name(g6, replace)
coefplot (mat(V1)) (mat(V2)) (mat(V3)), ///
recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*_a = "Group A" *_b = "Group B") ///
plotlab("Outcome 1" "Outcome 2" "Outcome 3") ///
xlab(0(0.5)3.5) name(g7, replace)
Automatic significance stars
Similar to using stored regression estimates, we can add automatic stars to our matrices. For this, we create a marker label (mlabel) for each coefficient, which consists of the appropriate number of stars or is empty. The marker option is directly included in the options for the subplot. This means that we will use a loop to collect all subplots with their specifications in a local, which we can use then in the coefplot command.
// Example 1: mean command & ttest
sysuse auto, clear
version 16
local mlist
local glist
foreach v of varlist rep78 headroom gear_ratio {
// get the label
local lab: var la `v'
// as before, run mean/regress command
qui mean `v', over(foreign)
// as before, store the matrix
mat m_`v' = r(table)[1,1...] \ r(table)[5,1...] \ r(table)[6,1...]
// test for significance
qui test `v'@0.foreign=`v'@1.foreign // remember how coefficients are stored
local s = cond(`r(p)'<.01, "***", cond(`r(p)'<.05, "**", cond(`r(p)'<.1, "*","")))
local mlist `mlist' (mat(m_`v'), ci((2 3)) mlabels(*1.foreign = 1 "`s'"))
// collect all names in a list (cf. last section)
local glist `glist' *`v'*=`"`lab'"'
}
coefplot `mlist', recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*0.foreign="Domestic" *1.foreign="Foreign") nokey ///
groups(`glist', angle(horizontal)) mlabcolor(none) ///
addplot(scatter @at @b, ms(i) mlabel(@mlbl) mlabcolor(black) mlabpos(1))
// Example 2: any regression & coefficient pvalue
sysuse auto, clear
version 16
local mlist
local glist
foreach v of varlist rep78 headroom gear_ratio {
// get the label
local lab: var la `v'
// as before, run mean/regress command
qui mean `v', over(foreign)
// as before, store the matrix
mat m_`v' = r(table)[1,1...] \ r(table)[5,1...] \ r(table)[6,1...]
// get column names (aka coefficient names)
loc c: colnames m_`v'
// the local function extracts the column names and adds "bn" for the basevalue --> delete
loc c = ustrregexra(`"`c'"',"bn(\.)",".",.)
// for full flexibiliy, loop
local slist
local n = 1
foreach w of local c {
local s = cond(r(table)[4,`n']<.01, "***", cond(r(table)[4,`n']<.05, "**", cond(r(table)[4,`n']<.1, "*","")))
local slist `slist' `w'= 1 "`s'"
loc n = `n'+1
}
local mlist `mlist' (mat(m_`v'), ci((2 3)) mlabels(`slist'))
// collect all names in a list (cf. last section)
local glist `glist' *`v'*=`"`lab'"'
}
di `"`mlist'"'
coefplot `mlist', recast(bar) citop fint(*.75) graphr(c(white)) nooffset ///
coeflab(*0.foreign="Domestic" *1.foreign="Foreign") nokey ///
groups(`glist', angle(horizontal)) mlabcolor(none) ///
addplot(scatter @at @b, ms(i) mlabel(@mlbl) mlabcolor(black) mlabpos(1))
Additional hints
To have the group names shown horizontally, change the option as follows
- groups(m1_*="Outcome 1" m2_*="Outcome 2" m3_*="Outcome 3", angle(horizontal))
To have the bars start directly at the axis (without a gap), add the option
- plotr(margin(zero))
To have no grid lines, add the options
- ytick(, nogrid)
- grid(none)
To have grid lines the other way round, add the options
- ytick(, nogrid)
- xlab(0(0.5)3.5, grid)