├── ex1.png
├── ex2.png
├── stata.toc
├── speccurve.pkg
├── README.md
├── speccurve_gendata.ado
├── speccurve.sthlp
└── speccurve.ado
/ex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/martin-andresen/speccurve/HEAD/ex1.png
--------------------------------------------------------------------------------
/ex2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/martin-andresen/speccurve/HEAD/ex2.png
--------------------------------------------------------------------------------
/stata.toc:
--------------------------------------------------------------------------------
1 | v 1.1
2 | d Martin Eckhoff Andresen, Statistics Norway
3 | p speccurve Stata package for plotting specirfication curves
4 |
--------------------------------------------------------------------------------
/speccurve.pkg:
--------------------------------------------------------------------------------
1 | v 1.1
2 | d speccurve Stata package to plot specification curves
3 | d
4 | d {bf:M. E. Andresenr, Research department, Statistics Norway}
5 | d Stata package to plot specification curves. After installation, see help {bf:mtefe}, help {bf:mtefeplot}.
6 | d
7 | d Distribution-Date: 20200826
8 | f speccurve.ado
9 | f speccurve.sthlp
10 | f speccurve_gendata.ado
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # speccurve
2 | Stata package to plot specification curves
3 |
4 | 
5 |
6 | Currently only works in Stata 16, makes ugly plots in earlier versions. Looking at it.
7 |
8 | Bugs likely, do report to martin.eckhoff.andresen@gmail.com
9 |
10 |
Installing development version
11 | net install speccurve, from("https://raw.githubusercontent.com/martin-andresen/speccurve/master")
12 |
--------------------------------------------------------------------------------
/speccurve_gendata.ado:
--------------------------------------------------------------------------------
1 | cap program drop speccurve_gendata
2 | {
3 | program define speccurve_gendata
4 | version 15.0
5 |
6 | syntax
7 |
8 | preserve
9 |
10 | cap which estadd
11 | if _rc!=0 {
12 | di in red "You need the estout package to add scalars to stored estimates, see -ssc install estout-."
13 | exit 301
14 | }
15 | clear all
16 | sysuse auto, clear
17 |
18 | cap rm estiv.ster
19 | cap rm estfs.ster
20 | cap rm estmod.ster
21 |
22 | //Linear regression models
23 |
24 | loc no=0
25 | qui foreach m in "" "mpg" {
26 | foreach h in "" "headroom" {
27 | foreach t in "" "trunk" {
28 | foreach g in "" "gear_ratio" {
29 | foreach l in "" "length" {
30 | foreach tu in "" "turn" {
31 | foreach r in "" "rep78" "i.rep78" {
32 | loc ++no
33 | reg price weight `m' `h' `t' `g' `l' `tu' `d' `r'
34 | estadd scalar no=`no'
35 | loc numc: word count `controls'
36 | estadd scalar numcontrols=`numc'
37 | eststo ols`no'
38 | }
39 | }
40 | }
41 | }
42 | }
43 | }
44 | }
45 |
46 |
47 |
48 | //IV models
49 | tokenize mpg headroom trunk gear_ratio turn displacement
50 |
51 | cap rm estfs.ster
52 | cap rm estiv.ster
53 |
54 | loc no=0
55 | qui forvalues mpg=0/1 {
56 | forvalues headroom=0/1 {
57 | forvalues trunk=0/1 {
58 | forvalues gear_ratio=0/1{
59 | forvalues turn=0/1 {
60 | forvalues displacement=0/1 {
61 | loc controls
62 | forvalues i=1/6 {
63 | if ```i'''==1 loc controls `controls' ``i''
64 | }
65 | loc ++no
66 | ivregress 2sls price (weight=length) `controls'
67 | estadd scalar no=`no'
68 | loc numc: word count `controls'
69 | estadd scalar numcontrols=`numc'
70 | estimates title: iv`no'
71 | est save estiv, append
72 |
73 | reg weight length `controls'
74 | estadd scalar no=`no'
75 | loc numc: word count `controls'
76 | estadd scalar numcontrols=`numc'
77 | estimates title: fs`no'
78 | est save estfs, append
79 | }
80 | }
81 | }
82 | }
83 | }
84 | }
85 |
86 | //Discrete choice models
87 | tokenize mpg headroom trunk gear_ratio
88 |
89 | cap rm estmod.ster
90 |
91 | loc no=0
92 |
93 | foreach mod in regress logit probit {
94 | qui forvalues mpg=0/1 {
95 | forvalues headroom=0/1 {
96 | forvalues trunk=0/1 {
97 | forvalues gear_ratio=0/1 {
98 | loc controls
99 | forvalues i=1/4 {
100 | if ```i'''==1 loc controls `controls' ``i''
101 | }
102 | loc ++no
103 | `mod' foreign weight `controls'
104 | if "`mod'"!="regress" margins, dydx(*) post
105 | estadd scalar no=`no'
106 | if "`mod'"=="regress" estadd scalar lpm=1
107 | else estadd scalar lpm=0
108 | if "`mod'"=="probit" estadd scalar probit=1
109 | else estadd scalar probit=0
110 | if "`mod'"=="logit" estadd scalar logit=1
111 | else estadd scalar logit=0
112 | loc numc: word count `controls'
113 | estadd scalar numcontrols=`numc'
114 | estimates title: mod`no'
115 | est save estmod, append
116 | }
117 | }
118 | }
119 | }
120 | }
121 |
122 | //SUBGROUP EXAMPLES
123 | tokenize mpg headroom trunk gear_ratio length turn displacement
124 |
125 | cap rm subgroups.ster
126 |
127 | loc no=0
128 | qui forvalues mpg=0/1 {
129 | forvalues headroom=0/1 {
130 | forvalues trunk=0/1 {
131 | forvalues gear_ratio=0/1{
132 | forvalues length=0/1 {
133 | forvalues turn=0/1 {
134 | forvalues displacement=0/1 {
135 |
136 | loc controls
137 | forvalues i=1/7 {
138 | if ```i'''==1 loc controls `controls' ``i''
139 | }
140 |
141 | forvalues f=0/1 {
142 | loc ++no
143 | reg price weight `controls' if foreign==`f'
144 | estadd scalar no=`no'
145 | estadd scalar foreign=`f'
146 | estadd scalar domestic=`=1-`f''
147 | loc numc: word count `controls'
148 | estadd scalar numcontrols=`numc'
149 | estimates title: subgroup`no'
150 | est save subgroups, append
151 | }
152 | loc ++no
153 | reg price weight `controls'
154 | estadd scalar no=`no'
155 | estadd scalar foreign=1
156 | estadd scalar domestic=1
157 | loc numc: word count `controls'
158 | estadd scalar numcontrols=`numc'
159 | estimates title: subgroup`no'
160 | est save subgroups, append
161 | }
162 | }
163 | }
164 | }
165 | }
166 | }
167 | }
168 |
169 |
170 |
171 | restore
172 | end
173 | }
174 |
--------------------------------------------------------------------------------
/speccurve.sthlp:
--------------------------------------------------------------------------------
1 | {smcl}
2 | {cmd:help speccurve}
3 | {hline}
4 |
5 | {title:Title}
6 |
7 | {p2colset 5 20 22 2}{...}
8 | {p2col:{cmd:speccurve} {hline 2}} Plot specification curve for estimates in memory or on disk.{p_end}
9 | {p2colreset}{...}
10 |
11 |
12 | {marker syntax}{...}
13 | {title:Syntax}
14 |
15 | {p 8 11 2}
16 | {cmd:speccurve} [namelist] [using] {cmd:,} param(name) [main(name) panel(namelist, {it:panel_opts}) controls[({it:panel_opts})] addplot([namelist]
17 | [samemodel] [using], param(name) {it:panel_opts}) level(numlist) keep(numlist) sort(name|none) fill graphopts(string) title(string) save(name)]
18 |
19 | {synoptset 25 tabbed}{...}
20 | {synopthdr}
21 | {synoptline}
22 | {syntab:Main}
23 | {synopt:{opt param(name)}} exact name of the coefficient of interest.{p_end}
24 | {synopt:{opt main(name)}} name of the main specification, which will be marked in the figure.{p_end}
25 | {synopt:{opt panel(namelist, [panel_opts])}} specification of a panel of characteristics for each estimate,
26 | see availabe options below. This option may be repeated multiple times for more panels. The order they are
27 | specified determines plot order.{p_end}
28 | {synopt:{opt controls([panel_opts])}} specifies that a specification panel is drawn, plotting which
29 | covariates (excluding the parameter of interest) is present in each specification. Options (which may
30 | be specified within parentheses) are detailed below. Order of the specification of this panel relative
31 | to the other specifications determines plot order.{p_end}
32 | {synopt:{opt addcoef([samemodel] [namelist] [using], param(name) [panel_opts])}} specifies that an additional plot is drawn, plotting
33 | the distribution of another coefficient of interest. param(name)-suboption is required, other options detailed
34 | below. Estimates are sorted according to the sort order in the main panel.{p_end}
35 | {synopt:{opt addscalar(name, [panel_opts])}} specifies that an additional scalar from e() is plotted in a separate panel. Estimates are sorted according to the sort order in the main panel.{p_end}
36 | {synopt:{opt level(numlist)}} level for confidence intervals, maximum 2. Default is 90 and 95% intervals.{p_end}
37 | {synopt:{opt keep(numlist)}} Must contain 3 nonnegative integers. Only the #1 smallest point estimates and the #3 largest point estimates are plotted, together with #2 other randomly drawn estimates.{p_end}
38 | {synopt:{opt graphopts(string)}} twoway options added to the main coefficient panel, use with caution.{p_end}
39 | {synopt:{opt sort(none|varname)}} changes sorting behavior. "none" does not sort estimates at all, "varname" sorts by specified variable. Default behaviour is to sort by estimate size.{p_end}
40 | {synopt:{opt title}} specifies the title of the main coefficient panel.{p_end}
41 | {synopt:{opt fill}} sets missing data for scalars specified in panel to 0.{p_end}
42 | {synopt:{opt save(name)}} saves the dataset in {it:name}, replacing any existing file by that name, before plotting and applying keep().{p_end}
43 | {synopt:{opt ytitle(string)}} names the main y-axis. Default is "coefficient on <>", where param is the main parameter of interest.{p_end}
44 |
45 | {syntab:panel_opts}
46 | {synopt:{opt labels(string)}} one-word labels used for each characteristic in the panel. Default: Name of scalar. {p_end}
47 | {synopt:{opt title(string)}} title of panel.{p_end}
48 | {synopt:{opt graphopts(string)}} other graph options, parsed directly to the twoway command that draws the panel.{p_end}
49 | {synoptline}
50 |
51 |
52 | {marker description}{...}
53 | {title:Description}
54 |
55 | {pstd}
56 | {cmd:speccurve} plots specifcation curves using stored or saved estimates of the same parameter with various specifications.{p_end}
57 |
58 | {pstd}
59 | If {it:using} is not specified, speccurve takes estimates from memory. If {it:using} is specified, speccurve takes estimates from the file
60 | using.ster. Either way, if {it:namelist} is specified, only estimates specified in namelist are used. Abbreviations and wildcards are allowed.
61 | If {it:namelist} is unspecified, all estimates in memory or in using.ster are used. When saving estimates, store one-word estimate names
62 | in estimates title using estimates title: yourname before saving if you want to use namelist to refer to some of them.{p_end}
63 |
64 | {pstd}
65 | Speccurve by default plots all estimates of the parameter of interest specified in param(name) with confidence bands.{p_end}
66 |
67 | {pstd}
68 | If the controls[()] option is specified (without parentheses allowed if not using suboptions), speccurve additionally plots a specification
69 | panel indicating with dots which covariates are included in each specification. Subobtions allowed, see below. If fixed effects are included, this
70 | option adds one line to this panel for each value of the fixed effects. Alternatively, users may manually specify an indicator for each set of fixed
71 | effects using the panel() option.{p_end}
72 |
73 | {pstd}If panel() is specified, speccurve additionally plots a user-specified specification panel using data specified in the panel() option.
74 | Panel() requires a namelist consisting of the names of scalars stored with each estimate to be plotted. This option may be repeated multiple
75 | times, and the order in which they are specified (and their relation to controls()-panel, if using) determines the order in which they are plotted.
76 | Subptions allowed, see below.{p_end}
77 |
78 | {pstd}
79 | If addcoef() is specified, speccurve plots an additional set of coefficients in a separate panel. param(name) suboption is required, specifying
80 | the name of the additional parameter of interest. If samemodel is specified in this option, speccurve looks for this coefficient in the same
81 | models already specified, in essence plotting a control variable. Alternatively, using may be specified to take these estimate from models stored
82 | in using.ster. If neither using nor samemodel is specified speccurve takes estimates from models in memory. Either way, only estimates specified
83 | in namelist is used, allowing wildcards, so that you may specify a subset of the estimates in memory or using.ster be used. Unless taking estimates
84 | from the same model as the main panel using samemodel, speccurve will assume that the order in which the models appear are the same as specified
85 | for the main coefficient of interest. Addplot allows further suboptions, see below.{p_end}
86 |
87 | {pstd}
88 | Addscalar() works similarly as addcoef, but plots an additional panel with a scatter plot of a scalar stored in e().
89 | {p_end}
90 |
91 | {pstd}Panel(), controls() and addplot() options all allow the suboptions title() and graphopts(), where the first specifies a title of the relevant
92 | panel and the latter specifies other {helpb twoway_options} to be added to the panel - use with caution because these may interfere with the panel
93 | spacing and alignment. Panel() and controls() also allows labels(), where the user can specify alternative one-word labels for each entry in the panel
94 | that appear on the y axis.{p_end}
95 |
96 | {pstd}Main() also allows the suboption graphopts(), which can similarly be used specify {helpb twoway_options} modifying its style.
97 |
98 | {marker preparation}{...}
99 | {title:Saving or storing your models before using speccurve}
100 |
101 | {pstd}
102 | {cmd:speccurve} takes results from saved (if specifying {it:using}) or stored (if not) models. Stata can store a maximum of 512 models in memory, so
103 | if the number of specifications exceed this, you need to save the estimates.{p_end}
104 |
105 | {pstd}
106 | First estimate your model using any e-class command that stores b and V in e(). If you want to use custom specification panels, you need to store
107 | scalars with the estimates indicating the details of the specification using estadd. As an example, add a scalar indicating that the "foreign"
108 | subsample was used by specifying estadd scalar "foreign=1" or add the number of the polynomial of some control using "estadd scalar polynomial=2".
109 | estadd is part of the estout package, see ssc -install estout-. If you are comparing estiamtes using different functional forms,
110 | you may wish to compute marginal effects using -margins, dydx(*) post- to store the marginal effects in e() before running speccurve.{p_end}
111 |
112 | {pstd}
113 | After all details of the specification is added to the estimate, either store the estimate using "eststo name", or add a title and save the estimate
114 | using "estimates title: name" (one word names only) followed by "estimates save filename, append", where append assures that you add the model to
115 | "filename" in addition to any models already stored there - all models must be saved in the same file.{p_end}
116 |
117 | {pstd}
118 | If you want a custom control panel, where for example fixed effects are indicated with a single line for a full set of fixed effect rather than a
119 | line for each level of the fixed effect, you'll need to add indicators for this manually, for example using estadd scalar county_fe=1 and later
120 | panel(county_fe) in speccurve to specify the panel manually.{p_end}
121 |
122 | {pstd}
123 | After doing this for all your specifications, you are ready to plot specification curves.{p_end}
124 |
125 | {marker confint}{...}
126 | {title:An note on confidence intervals}
127 |
128 | {pstd}
129 | Speccurve plots pointwise confidence intervals, meaning confidence intervals on the parameter of interest estimated for
130 | each model separately. This is in line with what is typically reported in robustness tables and figures. Note, however,
131 | that when formally testing the hypothesis that a coefficient from an alternative model is different from the coefficient from
132 | the baseline model, correct inference requires the models to be estimated simultaneously rather than simply comparing whether
133 | the pointwise confidence intervals overlap. Speccurve is purely a plotting tool and so does not estimate the models,
134 | but users are encouraged to estimate models simultaneously when formally testing hypotheses.
135 |
136 |
137 | {marker examples}{...}
138 | {title:Examples}
139 |
140 | {pstd}
141 | Examples models are estimated in speccurve_gendata:
142 |
143 | {pstd}
144 | Estimate a bunch of (arguably silly) models to use for examples. Load auto data and estimate 128 regressions of price on weight, controlling for all combinations
145 | of mpg, headroom, trunk, gear_ratio, length, turn and displacement. Store these in memory, calling them ols1-ols128. Add a dummy variable indicating the inclusion
146 | of each control, and also a numerical variable indicating the number of control variables used.
147 |
148 | {pstd}
149 | Estimate the same models again, but absorb fixed effects for rep78 using xtreg. Add a dummy for whether these factor variables was controlled for.
150 |
151 | {ptsd}
152 | Also estimate 48 2SLS models of price on weight with various controls, using length as an instrument for weight, and store these in
153 | estiv.ster, and the associated first stage regressions, storing them in estfs.ster.
154 |
155 | {ptsd}
156 | Estimate linear probability, logit and probit models of the probability that a car is foreign based on weight
157 | and various controls, store these in estmod.ster. {p_end}
158 |
159 | {ptsd}
160 | Finally estimate all the linear regressions models separately for foreign and domestic cars, and add a dummy indicating what sample was used.
161 |
162 | {ptsd}
163 |
164 | {phang2}({stata "speccurve_gendata":{it:click to run})}{p_end}
165 |
166 | {pstd}
167 | Specification plot with automatic control panel, highlight main specification {p_end}
168 | {phang2}{cmd:. speccurve, param(weight) controls main(ols1)}{p_end}
169 | {phang2}({stata "speccurve, param(weight) controls main(ols1)":{it:click to run}}){p_end}
170 |
171 | {pstd}
172 | Unfortunately this figure is a bit cluttered. Therefore just plot the smallest and largest 20 estimates and 20 random estimates in the middle:{p_end}
173 | {phang2}{cmd:. speccurve, param(weight) controls main(ols1) keep(20 20 20)} {p_end}
174 | {phang2}({stata "speccurve, param(weight) controls main(ols1) keep(20 20 20)":{it:click to run}}) {p_end}
175 |
176 | {pstd}
177 | Plot a panel indicating just the number of controls instead {p_end}
178 | {phang2}{cmd:. speccurve, param(weight) panel(numcontrols) main(ols1)}{p_end}
179 | {phang2}({stata "speccurve, param(weight) panel(numcontrols) main(ols1)":{it:click to run}}){p_end}
180 |
181 |
182 | {pstd}
183 | Use the addcoef() option to plot the values of the control variable length{p_end}
184 | {phang2}{cmd:. speccurve, param(weight) main(ols1) keep(20 20 20) controls addcoef(samemodel, param(length))} {p_end}
185 | {phang2}({stata "speccurve, param(weight) main(ols1) keep(20 20 20) controls addcoef(samemodel, param(length))":{it:click to run}}) {p_end}
186 |
187 | {pstd}
188 | Use the addscalar() option to plot a separate plot of R^2 from each model.{p_end}
189 | {phang2}{cmd:. speccurve, param(weight) main(ols1) keep(20 20 20) controls addscalar(r2, graphopts(ytitle(R squared)))} {p_end}
190 | {phang2}({stata "speccurve, param(weight) main(ols1) keep(20 20 20) controls addscalar(r2, graphopts(ytitle(R squared)))":{it:click to run}}) {p_end}
191 |
192 |
193 | {pstd}
194 | Plot the IV estimates from estiv.ster, a control panel and use the addcoef() option to plot the associated first stage estimates for each model, taking them from estfs.ster:{p_end}
195 | {phang2}{cmd:. speccurve using estiv, param(weight) main(iv1) keep(20 20 20) controls addcoef(using estfs, param(length) graphopts(ytitle(first stage estimates))) graphopts(ytitle(IV estimates))} {p_end}
196 | {phang2}({stata "speccurve using estiv, param(weight) main(iv1) keep(20 20 20) controls addcoef(using estfs, param(length) graphopts(ytitle(first stage estimates))) graphopts(ytitle(IV estimates))":{it:click to run}}) {p_end}
197 |
198 | {pstd}
199 | Plot the marginal effects of weight on the probability that a car is foreign from linera probability, logit and probit models with various controls, from estmod.ster:{p_end}
200 | {phang2}{cmd:. speccurve using estmod, param(weight) controls panel(lpm logit probit) graphopts(ytitle(marginal effect of weight))} {p_end}
201 | {phang2}({stata "speccurve using estmod, param(weight) controls panel(lpm logit probit) graphopts(ytitle(marginal effect of weight))":{it:click to run}}) {p_end}
202 |
203 | {pstd}
204 | Plot subgroup specific models (foreign vs domestic cars vs. both), adding a panel that indicates the subgroup:{p_end}
205 | {phang2}{cmd:. speccurve using subgroups, param(weight) panel(foreign domestic,title(subgroup)) controls(title(controls)) keep(20 20 20)} {p_end}
206 | {phang2}({stata "speccurve using subgroups, param(weight) panel(foreign domestic,title(subgroup)) controls(title(controls)) keep(20 20 20)":{it:click to run}}) {p_end}
207 |
208 | {marker saved_results}{...}
209 | {title:Stored results}
210 |
211 | {pstd}
212 | {cmd:speccurve} stores the following in {cmd:r()}:
213 |
214 | {synoptset 20 tabbed}{...}
215 | {synopt:{cmd:r(table)}}Matrix of plotted data{p_end}
216 |
217 | {marker Author}{...}
218 | {title:Author}
219 |
220 | {pstd}Martin Eckhoff Andresen{p_end}
221 | {pstd}University of Oslo & Statistics Norway{p_end}
222 | {pstd}Oslo, NO{p_end}
223 | {pstd}martin.eckhoff.andresen@gmail.com{p_end}
224 | {pstd}bugs, comments, feedback and feature requests welcome{p_end}
225 |
226 | {marker Thanks}{...}
227 | {title:Thanks to}
228 | {pstd}Uri Simonsohn, Joseph Simmons and Leif D. Nelson for their paper "Specification Curve Analysis"
229 | (Nat Hum Behav, 2020, and previous working paper), first (?) suggesting the specification curve.{p_end}
230 |
231 | {pstd}Hans H. Sievertsen for posting a graph that inspired this program on {browse "twitter.com/hhsievertsen/status/1188780383736909825":Twitter} {p_end}
232 |
--------------------------------------------------------------------------------
/speccurve.ado:
--------------------------------------------------------------------------------
1 | *! speccurve v1.2, 20240513
2 | * Author: Martin Eckhoff Andresen
3 |
4 | cap program drop speccurve panelparse speccurverun sortpreserve addcoefparse savecoefs
5 |
6 | program define speccurve
7 | version 16.0
8 |
9 | preserve
10 |
11 | loc panelno=0
12 | loc controlpanelno=0
13 | while `"`0'"' ! = "" {
14 | gettoken mac 0: 0, parse(" ") bind
15 | if substr("`mac'",1,5)=="panel" {
16 | loc panels `panels' `mac'
17 | loc ++panelno
18 | }
19 | else if substr("`mac'",1,8)=="controls" {
20 | if "`controladded'"!="" {
21 | noi di in red "Do not repeat the controls option"
22 | exit 301
23 | }
24 | loc controladded=1
25 |
26 | loc ++panelno
27 | loc controlpanelno=`panelno'
28 | if strpos("`mac'","(")>0 loc content `=substr("`mac'",strpos("`mac'","(")+1,`=strlen("`mac'")-strpos("`mac'","(")-1')'
29 | while "`content'"!="" {
30 | gettoken tok content: content, parse(" ") bind
31 | if substr("`tok'",1,6)=="labels" loc controllabels `=substr("`tok'",8,`=strlen("`tok'")-8')'
32 | else if substr("`tok'",1,5)=="title" loc controltitle `=substr("`tok'",7,`=strlen("`tok'")-7')'
33 | else if substr("`tok'",1,9)=="graphopts" loc controlgraphopts `=substr("`tok'",11,`=strlen("`tok'")-11')'
34 | else {
35 | noi di in red "Suboption `tok' not allowed in controls()."
36 | exit 301
37 | }
38 | }
39 | }
40 | else loc syntax `syntax' `mac'
41 | }
42 |
43 | speccurverun `syntax' panels(`panels') controlpanelno(`controlpanelno') controlgraphopts(`controlgraphopts') controltitle(`controltitle') controllabels(`controllabels')
44 |
45 |
46 | end
47 |
48 |
49 | * Author: Martin Eckhoff Andresen
50 | * Inspired by Uri Simonsohn, Joseph Simmons and Leif D. Nelson's paper on the specification curve and Hans H. Sievertsen @ Twitter
51 |
52 | program define speccurverun, rclass
53 | version 15.0
54 |
55 | syntax [anything] [using/] , param(name) [controlpanelno(integer 0) addcoef(string) controlpanel graphopts(string) controltitle(string) controllabels(string) controlgraphopts(string) main(string) panels(string) keep(numlist min=3 max=3 >=0 integer) level(numlist min=1 max=2 sort integer >0 <100) title(string) sort(name) save(name) fill addscalar(string) drop(string) ytitle(string)]
56 |
57 |
58 | qui {
59 | tempvar spec coefs r keepvar bin
60 | tempfile output
61 |
62 | loc numpanels=0
63 | while "`panels'"!="" {
64 | loc ++numpanels
65 | if `numpanels'==`controlpanelno' continue
66 | gettoken panel panels: panels, bind
67 | panelparse `=substr("`panel'",7,strlen("`panel'")-7)'
68 | loc panelvars`numpanels' `=s(panelvars)'
69 | loc numvars`numpanels'=s(numvars)
70 | loc labels`numpanels' `=s(labels)'
71 | if "`=s(graphopts)'"!="." loc graphopts`numpanels' `=s(graphopts)'
72 | if "`=s(title)'"!="." loc title`numpanels' `=s(title)'
73 | loc panelvars `panelvars' `panelvars`numpanels''
74 | }
75 | if `controlpanelno'>`numpanels' loc ++numpanels
76 |
77 | //sort option
78 | if !inlist("`sort'","none","") {
79 | loc sortvar `sort'
80 | }
81 |
82 | //control main opt
83 | if "`main'"!="" {
84 | mainparse `main'
85 | loc mainspec `s(mainspec)'
86 | loc maingraphopts `s(graphopts)'
87 | }
88 |
89 | //levels option
90 | if "`level'"=="" loc level 90 95
91 | loc numlevel: word count `level'
92 | loc i=0
93 | foreach lev in `level' {
94 | loc ++i
95 | loc level`i'=`lev'
96 | }
97 |
98 | //Parse addcoef() option
99 | if "`addcoef'"!="" {
100 | addcoefparse `addcoef'
101 | loc namelistaddcoef `s(namelist)'
102 | loc paramaddcoef `s(param)'
103 | loc addcoeftitle `s(title)'
104 | loc samemodel `s(samemodel)'
105 | loc addcoefusing `s(using)'
106 | loc addcoefscalar `s(scalar)'
107 | loc addcoefgraphopts `s(graphopts)'
108 | tempfile addcoefdata
109 | }
110 |
111 | //parse addscalar() option
112 |
113 | if "`addscalar'"!="" {
114 | addscalarparse `addscalar'
115 | loc addscalar `s(namelist)'
116 | loc addscalartitle `s(title)'
117 | loc addscalargraphopts `s(graphopts)'
118 | }
119 |
120 |
121 | //Create dataset from estimates
122 | clear
123 | foreach var in estimate `panelvars' `sortvar' `addscalar' modelno {
124 | cap gen `var'=.
125 | }
126 | gen parm=""
127 | gen name=""
128 | foreach lev in `level' {
129 | gen min`lev'=.
130 | gen max`lev'=.
131 | }
132 |
133 | if "`using'"!="" { //if taking data from .ster file
134 | cap estimates describe using `using'
135 | if _rc!=0 {
136 | noi di in red "Using file `using'.ster not found."
137 | exit 301
138 | }
139 | forvalues i=1/`=r(nestresults)' {
140 | estimates use `using', number(`i')
141 | loc modname `e(estimates_title)'
142 | if "`anything'"!="" {
143 | loc numwordstitle: word count `modname'
144 | if `numwordstitle'>1 {
145 | noi di in red "Use only one-word names for estimates titles when storing them on disk and specifying namelist. Estimate `modname' contains more than one word."
146 | exit 301
147 | }
148 | }
149 | if `controlpanelno'!=0 loc colnames: colnames e(b)
150 | else if "`addcoef'"!="" loc colnames `param' `paramaddcoef'
151 | else loc colnames `param'
152 | savecoefs `colnames', level(`level') scalars(`panelvars' `sortvar' `addscalar')
153 | replace modelno=`i' if modelno==.
154 | replace name="`modname'" if name==""
155 | }
156 | if "`anything'"!="" {
157 | gen `keepvar'==0
158 | foreach okname in `anything' {
159 | replace `keepvar'=1 if strmatch(name,"`okname'")==1
160 | }
161 | drop if `keepvar'==0
162 | drop `keepvar'
163 | levelsof name, local(namelist)
164 | }
165 |
166 | }
167 |
168 | else { //when taking estimates from memory
169 | est dir `anything'
170 | loc namelist `=r(names)'
171 | loc i=0
172 | foreach est in `namelist' {
173 | loc ++i
174 | est restore `est'
175 | if `controlpanelno'!=0 loc colnames: colnames e(b)
176 | else if "`addcoef'"!=""&"`samemodel'"!="" loc colnames `param' `paramaddcoef'
177 | else loc colnames `param'
178 | savecoefs `colnames', level(`level') scalars(`panelvars' `sortvar' `addscalar')
179 | replace name="`est'" if name==""
180 | replace modelno=`i' if modelno==.
181 | }
182 | }
183 |
184 | drop if parm=="_cons"
185 | if "`drop'"!="" {
186 | foreach dr in `drop' {
187 | drop if strpos(parm,"`dr'")>0
188 | }
189 | }
190 |
191 |
192 | //automatic control panel
193 | if `controlpanelno'!=0 {
194 |
195 | replace parm=regexr(parm,"(\d+)\.","i.") if parm!="`param'"&parm!="`paramaddcoef'"
196 | replace parm=regexr(parm,"(\d+)b\.","i.") if parm!="`param'"&parm!="`paramaddcoef'"
197 |
198 | bys name parm: drop if _n>1
199 |
200 | if "`samemodel'"=="" levelsof parm if parm!="`param'", local(parmlist) clean
201 | else levelsof parm if parm!="`param'"&parm!="`paramaddcoef'", local(parmlist) clean
202 |
203 | gen byte `bin'=.
204 | loc c=0
205 | foreach parm in `parmlist' {
206 | loc ++c
207 | replace `bin'=parm=="`parm'"
208 | tempname var`c'
209 | bys name: egen `var`c''=max(`bin')
210 | loc panelvars`controlpanelno' `panelvars`controlpanelno'' `var`c''
211 | }
212 | local numvars`controlpanelno': word count `panelvars`controlpanelno''
213 | if "`controltitle"!="" loc title`controlpanelno' `controltitle'
214 | if "`controllabels'"!="" loc labels`controlpanelno' `controllabels'
215 | else loc labels`controlpanelno' `parmlist'
216 | loc graphopts`controlpanelno' `controlgraphopts'
217 |
218 |
219 | }
220 |
221 | if "`samemodel'"!="" keep if inlist(parm,"`param'","`paramaddcoef'")
222 | else keep if parm=="`param'"
223 |
224 | //addcoef option
225 | if "`addcoef'"!="" {
226 | if "`samemodel'"=="" {
227 | if "`addcoefusing'"!="" { //when taking addcoef estimates from file
228 | cap estimates describe using `addcoefusing'
229 | if _rc!=0 {
230 | noi di in red "Using file `addcoefusing'.ster not found."
231 | exit 301
232 | }
233 | forvalues i=1/`=r(nestresults)' {
234 | estimates use `addcoefusing', number(`i')
235 | loc modname `e(estimates_title)'
236 | if "`namelistaddcoef'"!="" {
237 | loc numwordstitle: word count `e(estimates_title)'
238 | if `numwordstitle'>1 {
239 | noi di in red "Use only one-word names for estimates titles when storing them on disk and specifying namelist. Estimate `modname' contains more than one word."
240 | exit 301
241 | }
242 | }
243 | savecoefs `paramaddcoef', level(`level')
244 | replace modelno=`i' if modelno==.
245 | replace name="`modname'" if name==""
246 | }
247 | if "`namelistaddcoef'"!="" {
248 | gen `keepvar'=0
249 | foreach okname in `anything' {
250 | replace `keepvar'=1 if strmatch(name,"`okname'")==1
251 | }
252 | drop if `keepvar'==0
253 | drop `keepvar'
254 | }
255 |
256 | }
257 |
258 | else { //when taking estimates from memory
259 | est dir `namelistaddcoef'
260 | loc namelistaddcoef `=r(names)'
261 | loc i=0
262 | foreach est in `namelistaddcoef' {
263 | loc ++i
264 | est restore `est'
265 | savecoefs `paramaddcoef', level(`level')
266 | replace name="`est'" if name==""
267 | replace modelno=`i' if modelno==.
268 | }
269 | }
270 | }
271 |
272 | keep if inlist(parm,"`param'","`paramaddcoef'")
273 | gen n=1 if parm=="`param'"
274 | replace n=2 if parm=="`paramaddcoef'"
275 | keep min* max* estimate modelno name n parm `panelvars' `sortvar' `panelvars`controlpanelno''
276 | reshape wide estimate min* max* parm name `panelvars' `sortvar' `panelvars`controlpanelno'', i(modelno) j(n)
277 | foreach var in name `panelvars' `sortvar' `panelvars`controlpanelno'' {
278 | drop `var'2
279 | rename `var'1 `var'
280 | }
281 | fvexpand min* max* estimate* parm*
282 | foreach var in `r(varlist)' {
283 | if substr("`var'",-1,1)=="1" rename `var' `=substr("`var'",1,strlen("`var'")-1)'
284 | else rename `var' `=substr("`var'",1,strlen("`var'")-1)'_a
285 | }
286 | }
287 |
288 |
289 | //finalize dataset
290 | if "`sort'"!="none" {
291 | if "`sort'"=="" sort estimate
292 | else sort `sortvar'
293 | }
294 | gen `spec'=_n
295 |
296 | loc Nspec=_N
297 | if "`save'"!="" save `save', replace
298 |
299 | //DROP ESTIMATES IF KEEP() option specified
300 | if "`keep'"!="" {
301 | if "`sort'"!="" {
302 | noi di in red "Do not combine sort() and keep() options - keep requires default sorting on estimate size."
303 | exit 301
304 | }
305 | gettoken keep1 keep: keep
306 | gettoken keep2 keep3: keep
307 | if `keep1'+`keep2'+`keep3'>=`Nspec' {
308 | noi di as text "Sum of number of specifications to keep specified in keep() is larger than or equal to the total number of specifications. Option keep() ignored".
309 | loc keep
310 | }
311 | else {
312 | tempvar dum run
313 | gen `r'=runiform()
314 | gen `dum'=name=="`mainspec'"
315 | sort `dum' `spec'
316 | bys `dum': gen `run'=_n
317 | gen `keepvar'=(`dum'==1|`run'<=`keep1'|`run'>=_N-`keep3')
318 | sort `keepvar' `r'
319 | bys `keepvar': replace `keepvar'=1 if _n<=`keep2'&`keepvar'==0
320 | drop if `keepvar'!=1
321 | sort estimate
322 | replace `spec'=_n
323 | su `spec'
324 | loc Nspec=_N
325 | if "`mainspec'"!="" {
326 | su `spec' if name=="`mainspec'"
327 | if r(mean)<=`=`keep1'+`keep2'' {
328 | loc xline2=`keep1'+`keep2'+1.5
329 | if r(mean)<=`keep1' loc xline1=`keep1'+1.5
330 | }
331 | }
332 | if "`mainspec'"==""|"`xline1'"=="" loc xline1=`keep1'+0.5
333 | if "`mainspec'"==""|"`xline2'"=="" loc xline2=`Nspec'-`keep3'+0.5
334 | loc xlines xline(`xline1', lpattern(dot)) xline(`xline2', lpattern(dot))
335 | }
336 | }
337 |
338 | //Determine appropriate scatter symbol size
339 | loc msize `=4.5/`Nspec''
340 | loc labsize `=min(`=7/`Nspec'',0.25)'in
341 |
342 | //Determine appropriate text size
343 | loc cols=`numlevel'+1
344 | if "`mainspec'"!="" {
345 | loc ++cols
346 | loc notifmain if name!="`mainspec'"
347 | loc scattermain (scatter estimate `spec' if name=="`mainspec'", mcolor(maroon) msize(`msize'in) msymbol(diamond) `maingraphopts')
348 | if "`addcoef'"!="" loc scattermain_a (scatter estimate_a `spec' if name=="`mainspec'", mcolor(maroon) msize(`msize'in) msymbol(diamond)`maingraphopts')
349 | loc labmain label(`=`numlevel'+2' "main")
350 | loc mainorder=`numlevel'+2
351 | }
352 |
353 | su min`level`numlevel''
354 | loc ymin=r(min)
355 |
356 | if "`addcoef'"!="" {
357 | su min`level`numlevel''_a
358 | loc ymin_a=r(min)
359 | }
360 |
361 | if "`addscalar'"!="" {
362 | su `addscalar'
363 | loc minscalar=r(min)
364 | }
365 |
366 | if `numlevel'==2 loc orderci 1 2
367 | else loc orderci 1
368 |
369 | //Phantom labels, to align panels
370 | if `numpanels'>0 {
371 | forvalues pan=1/`numpanels' {
372 | foreach i in `labels`pan'' {
373 | loc phantomlabs `phantomlabs' `ymin' "`i'"
374 | loc phantomlabsscat `phantomlabsscat' 1 "`i'"
375 | if "`addcoef'"!="" loc phantomlabs_a `phantomlabs_a' `ymin_a' "`i'"
376 | if "`addscalar'"!="" loc phantomlabs_s `phantomlabs_s' `minscalar' "`i'"
377 | }
378 | }
379 |
380 |
381 | loc extraylabs ylabel(`phantomlabs', add custom labcolor(white%0) labsize(`labsize') angle(horizontal) tlcolor(white%0))
382 | if "`addcoef'"!="" loc extraylabs_a ylabel(`phantomlabs_a', add custom labcolor(white%0) labsize(`labsize') angle(horizontal) tlcolor(white%0))
383 | if "`addscalar'"!="" loc extraylabs_s ylabel(`phantomlabs_s', add custom labcolor(white%0) labsize(`labsize') angle(horizontal) tlcolor(white%0))
384 | loc extraylabsscat ylabel(`phantomlabsscat', add custom labcolor(white%0) labsize(`labsize') angle(horizontal) tlcolor(white%0))
385 | }
386 |
387 | loc j=0
388 | forvalues i=`numlevel'(-1)1 {
389 | loc ++j
390 | loc rbars `rbars' (rbar min`level`i'' max`level`i'' `spec', color(gs`=10+2*`i''%50) lwidth(none))
391 | if "`addcoef'"!="" loc rbarsaddcoef (rbar min`level`i''_a max`level`i''_a `spec', color(gs`=10+2*`i''%50) lwidth(none)) `rbarsaddcoef'
392 | loc labels `labels' label(`j' "`level`i''% CI")
393 | loc varnamesci `varnamesci' min`level`i'' max`level`i''
394 | }
395 |
396 | //Determine relative sizes of panels
397 | if "`title'"!="" loc ysizemain=4.3
398 | else loc ysizemain=4
399 | loc ysize=`ysizemain'
400 | if `numpanels'>0 {
401 | forvalues pan=1/`numpanels' {
402 | if "`title`pan''"=="" loc ysize`pan'=`msize'*(`numvars`pan''+1)+0.1
403 | else loc ysize`pan'=`msize'*(`numvars`pan''+1)+0.4
404 | loc ysize=`ysize'+`ysize`pan''
405 | }
406 | }
407 | if "`addcoef'"!="" {
408 | if "`addcoeftitle'"!="" loc ysizeaddcoef =4.3
409 | else loc ysizeaddcoef=4
410 | loc ysize=`ysize'+`ysizeaddcoef'
411 | }
412 |
413 | if "`addscalar'"!="" {
414 | if "`addscalartitle'"=="" loc ysizeaddscalar=4
415 | else loc ysizeaddscalar=4.3
416 | loc ysize=`ysize'+`ysizeaddscalar'
417 | }
418 |
419 | //Plot estimates
420 | if "`ytitle'"=="" loc ytitle coefficient on `param'
421 | if `numpanels'>0|"`addcoef'"!=""|"`addscalar'"!="" {
422 | loc nodraw nodraw
423 | loc coefname `coefs'
424 | loc margins 0 0 0 0
425 | }
426 | else loc coefname speccurve
427 | twoway `rbars' (scatter estimate `spec' `notifmain', mcolor(black) msize(`msize'in) msymbol(circle)) `scattermain' ///
428 | , name(`coefname', replace) scheme(s2mono) xscale(range(0.5 `=`Nspec'+0.5')) ///
429 | xlabel(none) xtitle("") graphregion(color(white)) plotregion(lcolor(black)) `xlines' ///
430 | title(`title', size(0.3in)) ylabel(#6, nogrid) ytitle("`ytitle'") ///
431 | `extraylabs' `nodraw' plotregion(margin(0.5 0.5 0.5 0.5)) graphregion(margin(`margins')) ///
432 | yline(0, lpattern(dash)) fysize(`=150*`ysizemain'/`ysize'') legend(`labels' label(`=`numlevel'+1' "estimates") `labmain' cols(`cols') order(`mainorder' `=`numlevel'+1' `orderci') position(5) ring(0)) `graphopts'
433 |
434 |
435 | //plot specification panel(s) + control panel
436 | if `numpanels'>0 {
437 | if strpos("`graphopts'","ytitle("")")>0&strpos("`addcoefgraphopts'","ytitle("")")>0&strpos("`addscalargraphopts'","ytitle("")")>0 loc pad
438 | else loc pad pad
439 |
440 | loc j=0
441 | forvalues pan=1/`numpanels' {
442 |
443 | loc labels
444 | loc i=0
445 | foreach lab in `labels`pan'' {
446 | loc ++i
447 | loc labels `labels' `=`numvars`pan''+1-`i'' "`lab'"
448 | }
449 |
450 | loc two
451 | loc k=0
452 | foreach i in `panelvars`pan'' {
453 | loc ++j
454 | loc ++k
455 | cap gen y`j'=`=`numvars`pan''+1-`k''
456 | levelsof `i', local(tmp)
457 | loc vals: word count `tmp'
458 | loc bin=0
459 | foreach val in `tmp' {
460 | if inlist(`val',0,1) loc bin=`bin'+1
461 | }
462 | if "`fill'"!="" loc fillstr |`i'==.
463 | if (`bin'==2&`vals'==2)|(`bin'==1&`vals'==1) { //plot scatters with dots
464 | loc two `two' (scatter y`j' `spec' if `i'==1&name!="`mainspec'", msymbol(circle) mcolor(black) msize(`msize'in) mlwidth(vthin)) ///
465 | (scatter y`j' `spec' if `i'==0`fillstr'&name!="`mainspec'", msymbol(circle_hollow) mlcolor(gs0) mcolor(white) msize(`msize'in) mlwidth(vthin)) ///
466 | (scatter y`j' `spec' if `i'==1&name=="`mainspec'", msymbol(circle) mcolor(maroon) msize(`msize'in) mlwidth(vthin)) ///
467 | (scatter y`j' `spec' if `i'==0`fillstr'&name=="`mainspec'", msymbol(circle_hollow) mlcolor(maroon) mcolor(white) msize(`msize'in) mlwidth(vthin))
468 | }
469 | else { //plot scatters with numbers/values
470 | loc two `two' (scatter y`j' `spec' if name!="`mainspec'"&`i'!=., mlabel(`i') mlabpos(0) msymbol(i) mlabsize(`msize'in)) ///
471 | (scatter y`j' `spec' if name=="`mainspec'"&`i'!=., mlabel(`i') mlabpos(0) msymbol(i) mlabcolor(maroon) mlabsize(`msize'in))
472 | }
473 | }
474 |
475 | tempvar plot`pan'
476 | twoway `two', nodraw ylabels(`labels', angle(horizontal) labsize(`labsize') nogrid) `extraylabsscat' ///
477 | scheme(s2mono) xscale(range(0.5 `=`Nspec'+0.5')) yscale(range(0.5 `=`numvars`pan''+0.5')) ///
478 | xlabel(none) xtitle("") legend(off) title(`title`pan'', size(0.3in)) ///
479 | plotregion(margin(0.5 0.5 0.5 0.5)) graphregion(margin(0 0 0 0)) ///
480 | graphregion(color(white)) plotregion(lcolor(black)) yscale(range(0.5 `=`numvars`pan''+0.5')) name(`plot`pan'', replace) fysize(`=150*`ysize`pan''/`ysize'') ysize(`ysize`pan'') ytitle("`pad'", color(white%0) ) `graphopts`pan''
481 |
482 | loc scatters `scatters' `plot`pan''
483 | }
484 |
485 |
486 | }
487 |
488 | //Plot additional coefficients or scalars from addcoef() or addscalar(
489 | if "`addcoef'"!="" {
490 | tempname addcoef1
491 | twoway `rbarsaddcoef' (scatter estimate_a `spec' `notifmain', mcolor(black) msize(`msize'in) msymbol(circle)) `scattermain_a' ///
492 | , name(`addcoef1', replace) scheme(s2mono) xscale(range(0.5 `=`Nspec'+0.5')) ///
493 | title(`addcoeftitle', size(0.3in)) xlabel(none) xtitle("") graphregion(color(white)) plotregion(lcolor(black)) `xlines' ///
494 | ylabel(#6, nogrid) ytitle("coefficient on `paramaddcoef'") plotregion(margin(0.5 0.5 0.5 0.5)) graphregion(margin(0 0 0 0)) ///
495 | `extraylabs_a' `nodraw' ///
496 | yline(0, lpattern(dash)) legend(off) fysize(`=150*`ysizeaddcoef'/`ysize'') `addcoefgraphopts'
497 | }
498 |
499 | if "`addscalar'"!="" {
500 | tempname addscalar1
501 | if "`mainspec'"!="" loc scattermain_s (scatter `addscalar' `spec' if name=="`mainspec'", mcolor(maroon) msize(`msize'in) msymbol(diamond))
502 | twoway (scatter `addscalar' `spec' `notifmain', mcolor(black) msize(`msize'in) msymbol(circle)) `scattermain_s' ///
503 | , name(`addscalar1', replace) scheme(s2mono) xscale(range(0.5 `=`Nspec'+0.5')) ///
504 | title(`addscalartitle', size(0.3in)) xlabel(none) xtitle("") graphregion(color(white)) plotregion(lcolor(black)) `xlines' ///
505 | ylabel(#6, nogrid) ytitle("`addscalar'") plotregion(margin(0.5 0.5 0.5 0.5)) graphregion(margin(0 0 0 0)) `nodraw' ///
506 | yline(0, lpattern(dash)) legend(off) fysize(`=150*`ysizeaddscalar'/`ysize'') `addscalargraphopts' `extraylabs_s'
507 | }
508 |
509 | if `numpanels'>0|"`addcoef'"!=""|"`addscalar'"!="" graph combine `coefs' `scatters' `addcoef1' `addscalar1', cols(1) graphregion(color(white)) imargin(0 0 0 0) ysize(`ysize') name(speccurve, replace)
510 |
511 |
512 |
513 | //Add resulting table to r(table)
514 | rename `spec' specno
515 | tempname table
516 | mkmat specno modelno estimate `varnamesci' `panelvars' `panelvars`controlpanelno'' `addscalar', matrix(`table') rownames(name)
517 | return matrix table=`table'
518 |
519 | }
520 |
521 | end
522 |
523 |
524 | //panelparse version 0.1
525 |
526 | program panelparse, sclass
527 | syntax namelist, [labels(string)) title(string) graphopts(string)]
528 | loc numvars: word count `namelist'
529 | sret local numvars=`numvars'
530 | sret local panelvars `namelist'
531 | while `"`labels'"'!="" {
532 | gettoken lab labels: labels
533 | loc labs `labs' `lab'
534 | gettoken name namelist: namelist
535 | }
536 | while "`namelist'"!="" {
537 | gettoken name namelist: namelist
538 | loc labs `labs' `name'
539 | }
540 | sret local labels `labs'
541 | sret local title `title'
542 |
543 | sret local graphopts `graphopts'
544 | end
545 |
546 | //mainparse
547 |
548 | program mainparse, sclass
549 | syntax namelist, [graphopts(string)]
550 | loc nummain: word count `namelist'
551 | if `nummain'>1 {
552 | noi di in red "Specify only one word or number in main(), corresponding to the name or number of the main specification."
553 | exit 301
554 | }
555 | sret local mainspec `namelist'
556 | sret local graphopts `graphopts'
557 | end
558 |
559 | //addcoefparse
560 |
561 | program addcoefparse, sclass
562 | syntax [anything] [using/], param(name) [title(string) graphopts(string) scalar(name)]
563 | if strpos("`anything'","samemodel")>0 {
564 | loc numnames: word count `anything'
565 | if `numnames'>1 {
566 | noi di in red "When specifying samemodel in addcoef(), do not specify a namelist - addcoef() coefficients are `param' from main models."
567 | exit 301
568 | }
569 | loc namelist
570 | loc samemodel samemodel
571 | }
572 | sret local param `param'
573 | sret local namelist `anything'
574 | sret local title `title'
575 | sret local graphopts `graphopts'
576 | sret local samemodel `samemodel'
577 | sret local using `using'
578 | sret local scalar `scalar'
579 |
580 | end
581 |
582 | //addscalarparse
583 |
584 | program addscalarparse, sclass
585 | syntax name, [title(string) graphopts(string)]
586 | foreach str in namelist title graphopts {
587 | sret local `str' ``str''
588 | }
589 |
590 | end
591 |
592 |
593 |
594 | //savecoefs
595 | program savecoefs
596 | syntax [anything], level(numlist min=1 max=2 integer >0 <100) [scalars(namelist)]
597 | loc k=0
598 | foreach lev in `level' {
599 | loc ++k
600 | tempname r`lev'
601 | eret di, level(`lev')
602 | mat `r`lev''=r(table)
603 | loc level`k'=`lev'
604 | }
605 |
606 | if "`anything'"=="" loc anything: colnames e(b)
607 | loc nparms: word count `anything'
608 | loc N=_N
609 | set obs `=_N+`nparms''
610 | foreach var in `scalars' {
611 | replace `var'=e(`var') if `var'==.
612 | }
613 | loc j=0
614 | foreach parm in `anything' {
615 | loc ++j
616 | cap replace parm="`parm'" in `=`N'+`j''
617 | cap replace estimate=`r`level1''[`=rownumb(`r`level1'',"b")',`=colnumb(`r`level1'',"`parm'")'] in `=`N'+`j''
618 | cap replace min`level1'=`r`level1''[`=rownumb(`r`level1'',"ll")',`=colnumb(`r`level1'',"`parm'")'] in `=`N'+`j''
619 | cap replace max`level1'=`r`level1''[`=rownumb(`r`level1'',"ul")',`=colnumb(`r`level1'',"`parm'")'] in `=`N'+`j''
620 | if `k'==2 {
621 | cap replace min`level2'=`r`level2''[`=rownumb(`r`level2'',"ll")',`=colnumb(`r`level2'',"`parm'")'] in `=`N'+`j''
622 | cap replace max`level2'=`r`level2''[`=rownumb(`r`level2'',"ul")',`=colnumb(`r`level2'',"`parm'")'] in `=`N'+`j''
623 | }
624 | }
625 |
626 | end
627 |
628 |
629 |
630 |
631 |
--------------------------------------------------------------------------------