-
Notifications
You must be signed in to change notification settings - Fork 1
/
ivxtile.ado
109 lines (98 loc) · 3.08 KB
/
ivxtile.ado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
*! version 0.1.0 16sep2021 Tom Palmer
* Acknowledge prefix command code from
* https://www.elwyndavies.com/stata-tips/create-a-stata-program-that-functions-as-a-prefix/
program define ivxtile
version 10
* Split the overall command, stored in `0' in a left and right part.
gettoken left right2 : 0, parse(":")
if `"`left'"' == ":" {
local right `"`right2'"'
}
else {
gettoken right3 right : right2, parse(":")
}
* Now, do the regular syntax parsing
local 0 : copy local left
local 0 = subinstr("`0'", ":", "", .)
syntax, par(string) [SAving(string) trace *]
local leftoptions `options'
if "`saving'" == "" {
tempfile saving
local savefilename `saving'
local savereplace ""
}
else {
tokenize `"`saving'"', parse(",")
local savefilename `1'
local savereplace `2' `3'
}
tempfile origdata
qui save `origdata'
* Run any code you want to run before the command on the right
local 0 : copy local right
syntax [anything] [if] [in] [, *]
tokenize `"`right'"'
local ivcmdname `1'
macro shift
local rest `*'
if "`ivcmdname'" == "ivregress" {
local rest = subinstr("`rest'", "2sls", "", .)
local rest = subinstr("`rest'", "liml", "", .)
local rest = subinstr("`rest'", "gmm", "", .)
}
_iv_parse `rest'
local lhs `s(lhs)'
local endog `s(endog)'
local exog `s(exog)'
local inst `s(inst)'
qui regress `endog' `inst' `exog' `if'`in'
tempvar residuals
qui predict double `residuals' `if'`in', residuals
tempvar resquantiles
xtile `resquantiles' = `residuals' `if'`in', `leftoptions'
qui levelsof `resquantiles' `if'`in'
local levels = r(levels)
* Now, run the command on the right
if inlist("`ivcmdname'", "ivtsps", "ivtsri") local par `par':_cons
if "`ivcmdname'" == "ivlsmm" local par cmxb_`par':_cons
tempname memhold
postfile `memhold' quantile beta se medendog using `savefilename' `savereplace'
if "`trace'" == "" local quietly quietly
else local noisily noisily
`quietly' foreach quant of local levels {
di _n "First stage residuals quantile: `quant'" _n
preserve
qui count if `resquantiles' == `quant'
if `r(N)' == 0 {
di as error "No observations in quantile `quant'"
error 2000
}
else if `r(N)' > 0 & `r(N)' < 10 {
di as txt "Only `r(N)' observations in quantile `quant'"
}
qui keep if `resquantiles' == `quant'
qui su `endog', detail
local medendog = r(p50)
capture `noisily' `right'
if _rc == 0 & ((inlist("`ivcmdname'", "ivtsps", "ivtsri", "ivlsmm", "ivmsmm") & e(converged) == 1) | inlist("`ivcmdname'", "ivregress", "ivreg2")) {
post `memhold' (`quant') (_b[`par']) (_se[`par']) (`medendog')
}
else {
noisily di as txt _n "Model did not fit in quantile `quant'"
post `memhold' (`quant') (.) (.) (`medendog')
}
restore
}
postclose `memhold'
use `savefilename', clear
qui gen lowci = beta - 1.96 * se
qui gen uppci = beta + 1.96 * se
label variable beta "Estimated causal effect"
label variable medendog "Median of exposure in quantile"
list , clean noobs
twoway line b lowci uppci medendog, sort(quantile) ///
lc(gs0 gs10 gs10) lw(medthick medthick medthick) ///
legend(rows(1) order(1 "Estimated causal effect" 2 "95% CI limits") pos(6)) ///
ytitle("Estimated causal effect")
use `origdata', clear
end