/* Sep 24 2023 Hongyu Mou, Yiqing Xu Version 1.0.0 */ capture program drop panelview program define panelview version 15.1 syntax varlist(min = 1 numeric) [if] [in] , /// I(varname) T(varname numeric) /// TYPE(string) /// [ /// continuoustreat /// discreteoutcome /// bytiming /// ignoretreat /// ignoreY /// MYCOLor(string) /// PREpost /// xlabdist(integer 1) /// ylabdist(integer 1) /// bygroup /// style(string) /// byunit /// theme(string) /// lwd(string) /// leavegap /// bygroupside /// displayall /// bycohort /// collapsehistory /// * /// ] //check if i and t uniquely identify the obs: isid `i' `t' //check needed packages cap which colorpalette.ado if _rc { *di as error "colorpalette.ado required: {stata ssc install palettes, replace}" di as error "colorpalette.ado required: {stata search gr0075} and click to install, and please make sure the other required packages (labutil, sencode, grc1leg) are installed" exit 199 } cap which labmask.ado if _rc { di as error "labmask.ado required: {stata ssc install labutil, replace}, and please make sure the other required packages (gr0075, sencode, grc1leg) are installed" exit 199 } cap which sencode.ado if _rc { di as error "sencode.ado required: {stata ssc install sencode, replace}, and please make sure the other required packages (labutil, gr0075, grc1leg) are installed" exit 199 } cap which grc1leg.ado if _rc { di as error "grc1leg.ado required: {stata search grc1leg} and click to install, and please make sure the other required packages (labutil, gr0075, sencode) are installed" exit 199 } //check for bad option combinations: if "`continuoustreat'" != "" { if "`bytiming'" != "" { di as err "options continuoustreat and bytiming may not be combined" exit 198 } } if "`continuoustreat'" != "" { if "`ignoretreat'" != "" { di as err /// "options continuoustreat and ignoretreat may not be combined" exit 198 } } if "`continuoustreat'" != "" { if ("`type'" == "miss" | "`type'" == "missing") { di as err /// "options continuoustreat and type(missing) may not be combined" exit 198 } } if ("`bygroup'" != "") { if ("`prepost'" == "") { *di as err /// "options bygroup and prepost should be combined" *exit 198 loc prepost 1 } } if ("`bygroupside'" != "") { if ("`bygroup'" == "") { loc bygroup 1 } if ("`prepost'" == "") { loc prepost 1 } } if ("`type'" == "outcome") { if ("`bytiming'" != "") { di as err /// "options type(outcome) and bytiming may not be combined" exit 198 } } if ("`type'" != "outcome") { if ("`bygroup'" != "") { di as err /// "option bygroup should be combined with type(outcome)" exit 198 } } if ("`type'" != "treat") { if ("`collapsehistory'" != "") { di as err /// "option collapsehistory should be combined with type(treat)" exit 198 } } if ("`leavegap'" != "") { if ("`collapsehistory'" != "") { di as err /// "options collapsehistory and leavegap should not be combined" exit 198 } } if ("`type'" != "outcome") { if ("`bycohort'" != "") { di as err /// "option bycohort should be combined with option type(outcome)" exit 198 } } if ("`type'" == "outcome" | "`type'" == "bivar") { if ("`leavegap'" != "") { di as err /// "option leavegap should be combined with type(treat) or type(missing)" exit 198 } } if ("`type'" != "treat" & "`type'" != "miss" & "`type'" != "missing") { if ("`ignoreY'" != "") { di as err /// "option ignoreY should be combined with type(treat) or type(missing)" exit 198 } } if ("`ignoretreat'" != "") { if ("`ignoreY'" != "") { di as err /// "option ignoreY should not be combined with ignoretreat" exit 198 } } if ("`ignoretreat'" != "") { if ("`collapsehistory'" != "") { di as err /// "option collapsehistory should not be combined with ignoretreat" exit 198 } } if ("`ignoretreat'" != "") { if ("`type'" == "miss" | "`type'" == "missing") { di as err /// "option type(missing) should not be combined with ignoretreat" exit 198 } } if ("`leavegap'" != "") { if ("`prepost'" != "") { di as err /// "option leavegap is not recommended to be combined with prepost" exit 198 } } if ("`bycohort'" != "") { loc leavegap 1 } set trace off //check if "type" is specified correctly: if ("`type'" != "miss" & "`type'" != "missing" & "`type'" != "treat" & "`type'" != "outcome" & "`type'" != "bivar" &"`type'" != "bivariate") { di as err /// "option type can only be one of the following: treat, outcome, bivariate (bivar), and missing (miss)" exit 198 } preserve tempfile backup qui keep `varlist' `i' `t' //only keep using variables, i.e. include covariates qui ds `varlist' tempvar numvar cap gen `numvar' = `: word count `r(varlist)'' /* if ("`ignoretreat'" != "" | "`type'" == "miss" | "`type'" == "missing") { if `numvar' > 1 { di "All variables other than the first is omitted" } } */ if `numvar' == 1 { if ("`ignoretreat'" == "" & "`type'" != "miss" & "`type'" != "missing" & "`type'" != "treat" & "`type'" != "outcome") { di as err "should combine with option ignoretreat, type(missing), type(treat) , or type(outcome) when varlist has only one variable" exit 198 } else if ("`type'" == "miss" | "`type'" == "missing") { tokenize `varlist' loc outcome `1' loc treat `1' } else if ("`type'" == "treat") { tokenize `varlist' loc treat `1' } else { //"`type'" == "outcome" tokenize `varlist' loc outcome `1' loc ignoretreat 1 } } else if `numvar' == 2 { if ("`ignoreY'" != "") { tokenize `varlist' loc treat `1' } else { if ("`ignoretreat'" != ""|"`type'" == "miss" | "`type'" == "missing") { tokenize `varlist' loc outcome `1' loc treat `1' *loc covariates `2' *drop if mi(`covariates') } else { tokenize `varlist' loc outcome `1' loc treat `2' } } } else { //`numvar' >= 3: if ("`ignoreY'" != "") { tokenize `varlist' loc treat `1' } else { if ("`ignoretreat'" != ""|"`type'" == "miss" | "`type'" == "missing") { tokenize `varlist' loc outcome `1' } else { tokenize `varlist' loc outcome `1' loc treat `2' } } } qui save `backup',replace if ("`type'" == "treat" | "`type'" == "miss" | "`type'" == "missing") { tempfile backup_misstable marksample touse //drop missing from controls sss tempvar countmissvar minrowmiss qui replace `touse' = . if `touse' == 0 qui egen `countmissvar' = rowmiss(`touse') qui bysort `i': egen `minrowmiss' = min(`countmissvar') *cap drop if `minrowmiss' != 0 //table right, figure wrong sss //cap drop if `touse' == 0 //figure right, table wrong // misschk `varlist', extmiss // search misschk; install spost9_ado // strip off string variables tempvar varlist1 loc varlist1 `varlist' parse "`varlist1'", parse(" ") local vars while "`1'" != "" { // loop through variables capture confirm numeric variable `1' if _rc==0 { local vars "`vars' `1'" } mac shift } local varlist1 "`vars'" parse "`varlist1'", parse(" ") local nvar = 0 di _n in g " # Variable # Missing % Missing" di in g "--------------------------------------------" tempvar ifin mark `ifin' `if' `in' quietly tab `ifin' local total = r(N) *display `total' while "`1'" != "" { // loop through variables local ++nvar //qui count if `1'>=. // count missing; qui count if `1'>=. & `ifin' // count missing; * create binary variables indicating if observation is missing if "`dummy'"~="" { if "`replace'"=="replace" { capture drop `gennm'`1' } //quietly gen `gennm'`1' = (`1'>=.) // quietly gen `gennm'`1' = (`1'>=.) if `ifin' // label var `gennm'`1' "Missing value for `1'?" label val `gennm'`1' lmisschk } * list # and percent missing di in y %3.0f " `nvar' " _col(7) "`1'" /// _col(23) %7.0f r(N) _col(36) %6.1f 100*r(N)/`total' mac shift } // loop through list of variables parse "`varlist1'", parse(" ") // loop through all variables and count missing tempvar ismissn ismissw missw missn quietly gen `missn' = 0 if `ifin' label var `missn' "Missing for how many variables?" quietly gen str1 `missw' = "" if `ifin' label var `missw' "Missing for which variables?" local nvar = 0 //local i = 0 local ext "a b c d e f g h i j k l m n o p q r s t u v w x y z" // 1.1.0 while "`1'" != "" { local ++nvar * ones has only one's digit of variable number local ones = mod(`nvar',10) * drop tempvars from last loop capture drop `ismissn' `ismissw' * 1 if mssing, else 0; . if not in if in capture quietly gen `ismissn' = (`1'>=.) if `ifin' // changed == 1.1.0 * string with indicator of missing status. Space if no missing; * then if missing, either . or digit number. capture quietly gen str1 `ismissw' = "`notmissstr'" quietly replace `ismissw' = "." if `1'==. & `ifin' foreach ltr in `ext' { quietly replace `ismissw' = "`ltr'" if `1'==.`ltr' & `ifin' } * add blank every 5th variable if mod(`nvar'-1,5) == 0 { quietly replace `missw' = `missw' + " " } * build string with pattern of missing data quietly replace `missw' = `missw' + `ismissw' * count total number of missing for given case quietly replace `missn' = `missn' + `ismissn' mac shift } capture drop `ismissn' `ismissw' // List results * patterns of missing data *tab `missw' if `ifin', `nosort' * number missing for given observations tab `missn' if `ifin' qui save `backup_misstable', replace } qui use `backup', clear marksample touse //drop missing from controls if "`leavegap'" == "" { cap drop if `touse' == 0 } else if "`leavegap'" != "" { tempvar countmissvar minrowmiss qui replace `touse' = . if `touse' == 0 qui egen `countmissvar' = rowmiss(`touse') qui bysort `i': egen `minrowmiss' = min(`countmissvar') cap drop if `minrowmiss' != 0 } quietly count if `touse' if r(N) == 0 { error 2000 } local ids `i' local tunit `t' //limit the unit number: bysort `i': gen nvals = (_n == 1) qui count if nvals *di "`r(N)'" if ("`bycohort'" == "" ) { if (r(N) > 500 & "`displayall'" == "") { di "If the number of units is more than 500, we randomly select 500 units to present. You can use displayall option to show all units" tempfile holding qui save `holding' qui keep `i' qui duplicates drop set seed 1234 qui sample 500, count qui merge 1:m `i' using `holding', assert(match using) keep(match) nogenerate } } tempvar nids cap label list `ids' if "`r(k)'" != "" { //numeric units indicator with labels: qui egen `nids' = group(`ids') *label list `ids' } else { //numeric units indicator without labels or string variable: capture confirm numeric variable `ids' if !_rc { //numeric units indicator without labels: tempvar labelids qui tostring `ids', gen(`labelids') labmask `ids', val(`labelids') *label list `ids' qui egen `nids' = group(`ids') } else { //string variable: tempvar i_numeric labeli qui encode `ids',gen(`i_numeric') *label list `i_numeric' drop `ids' rename `i_numeric' `ids' qui egen `nids' = group(`ids') } } qui levelsof `nids' if `touse' loc numids = r(r) // ignore treatment: tempvar gcontrol capture confirm variable `treat' if !_rc { qui levelsof `treat' if `touse', loc (levstreat) loc numlevstreat = r(r) if ("`bycohort'" != "" & `numlevstreat' != 2) { di as err "option bycohort works only with dummy treatment variable" exit 198 } } capture assert `treat' == 0 | `treat' == 1 if ("`bycohort'" != "" & _rc) { di as err "option bycohort works only with dummy treatment variable" exit 198 } if ("`ignoretreat'" != "" | "`type'" == "miss" | "`type'" == "missing") { cap gen `gcontrol' = 1 } *if ("`continuoustreat'" != "" & "`type'" == "outcome") { else if (`numlevstreat' > 2 & "`type'" == "outcome") { cap gen `gcontrol' = 1 } else { *if ("`ignoretreat'" != "" | "`type'" == "miss" | "`type'" == "missing") { *cap gen `gcontrol' = 1 *} *else { if (`numlevstreat' == 2) { tempvar max_treat cap bys `nids': egen `max_treat' = max(`treat') cap gen `gcontrol' = 1 qui replace `gcontrol' = 0 if `max_treat' >= 1 } else { if (`numlevstreat' == 1) { di "Only one treatment level" cap gen `gcontrol' = 1 } else { if ("`prepost'" != "") { di as err "with more than two treatment levels, option prepost may not be combined" exit 198 } else { if (`numlevstreat' >= 5 & "`continuoustreat'" == "") { di "Too many treatment levels; treat as continuous." local continuoustreat `"continuoustreat"' cap gen `gcontrol' = 1 } if (`numlevstreat' <= 4 & "`continuoustreat'" != "") { di "Too few treatment levels; consider drop the continuoustreat option." } } } } *} } sort `ids' `tunit' //sort by time of first treatment if "`bytiming'" != "" { tempvar bytime tempvar min_bytime tempvar num_trtime cap gen `bytime' = . cap replace `bytime' = `tunit' if `treat' > = 1 cap bys `nids': egen `min_bytime' = min(`bytime') cap bys `nids': egen `num_trtime' = count(`bytime') drop `bytime' tempvar nids2 tempvar nids3 decode `ids', generate(`nids2') sencode `nids2', generate(`nids3') gsort(`min_bytime' -`num_trtime' `ids') *tab `min_bytime',m // missing: controls *tab `num_trtime',m // 0: controls *tab `ids',m } else { tempvar nids2 nidslab decode `ids', generate(`nids2') sencode `nids2', generate(`nidslab') } qui levelsof `nids' if `touse' , loc (levsnids) /* tempvar newtime egen `newtime' = group(`tunit') *qui sum `newtime' *loc maxmintime = r(max) - r(min) *qui levelsof `newtime' *loc numsoftime = r(r) *loc plotcoef = `maxmintime' / (`numsoftime' -1) tempvar labeltime qui tostring `tunit', gen(`labeltime') labmask `newtime', val(`labeltime') */ tempvar maxtime mintime timegap inttimegap timegap2 mintimegap id_oneobs cap bysort `nids': gen `maxtime' = `tunit'[_N] qui sum `maxtime' loc maxmaxtime = r(max) cap bysort `nids': egen `mintime' = min(`tunit') qui sum `mintime' loc minmintime = r(min) loc maxmaxminmingap = `maxmaxtime' - `minmintime' qui levelsof `tunit' loc numtime = r(r) cap gen `timegap' = (`maxmaxminmingap')/(`numtime'-1) //possible common difference qui gen `inttimegap' = int(`timegap') cap bysort `nids': gen `timegap2' = `tunit'[_n]-`tunit'[_n-1] cap bysort `nids': egen `mintimegap' = min(`timegap2') if "`leavegap'" != "" { if ( `timegap' != `mintimegap' | `inttimegap' != `timegap') { //not arithmetic sequence tempvar differencetime cap bysort `nids': gen `differencetime' = `tunit'[_n] - `tunit'[_n-1] qui sum `differencetime' loc min_differencetime = r(min) loc max_differencetime = r(max) loc divide_differencetime = `max_differencetime' / `min_differencetime' if (`min_differencetime' != `max_differencetime' & `min_differencetime' != 1 & `divide_differencetime' == int(`divide_differencetime')) { // 两两difference相除是整数倍 qui save `backup', replace qui keep `nids' qui duplicates drop `nids', force qui expand `numtime' cap bysort `nids': gen `tunit' = `minmintime' + (_n-1) * `min_differencetime' qui merge 1:1 `nids' `tunit' using `backup' qui drop _merge } else { //commmon difference = 1 qui save `backup', replace qui keep `nids' qui duplicates drop `nids', force qui expand `maxmaxminmingap' cap bysort `nids': gen `tunit' = `minmintime' + _n qui merge 1:1 `nids' `tunit' using `backup' qui drop _merge } } } if "`leavegap'" == "" { loc alltimegap = `maxmaxminmingap'/(`numtime'-1) if (`timegap' != `mintimegap' | `inttimegap' != `timegap') { di "Time is not evenly distributed (possibly due to missing data). " } else { tempvar tunit_merge qui gen `tunit_merge' = `tunit' qui save `backup', replace qui keep `nids' qui duplicates drop `nids', force qui expand `numtime' cap bysort `nids': gen `tunit_merge' = `minmintime' + (_n-1) * `alltimegap' qui merge 1:1 `nids' `tunit_merge' using `backup' tempvar difftime qui gen `difftime' = (`tunit_merge' == `tunit') qui sum `difftime' loc min_difftime = r(min) loc max_difftime = r(max) *if (`max_difftime' != `min_difftime') { *if (`alltimegap' != 1) { *di "Time is not evenly distributed (possibly due to missing data). " *} *} qui drop `tunit_merge' qui drop _merge } } tempvar newtime qui egen `newtime' = group(`tunit') tempvar labeltime qui tostring `tunit', gen(`labeltime') labmask `newtime', val(`labeltime') //indicate the last period as a different colored dot in outcome plot if only treated in the last period: tempvar lastchangedot maxtime2 dtreat islastchangedot cap bysort `nids': gen `maxtime2' = `tunit'[_N-1] cap gen `lastchangedot' = 0 cap bysort `nids': replace `lastchangedot' = 1 if `treat' == 1 & `tunit' == `maxtime' cap bysort `nids': gen `dtreat' = `treat'[_N] - `treat'[_N-1] if `lastchangedot' == 1 cap bysort `nids': replace `lastchangedot' = 0 if `dtreat' == 0 cap count if `lastchangedot' == 1 loc islastchangedot = (r(N) != 0) /* //paint the period right before treatment: if ("`ignoretreat'" == "" & "`type'" != "miss" & "`type'" != "missing") { if ("`type'" == "outcome" & "`discreteoutcome'" == "" ) { cap destring `labeltime', replace tempvar L1_labeltime L1_time cap bys `nids': gen `L1_labeltime' = `labeltime'[_n-1] if `treat' >= 1 cap bys `nids': egen `L1_time' = min(`L1_labeltime') cap replace `treat' = 1 if `labeltime' == `L1_time' } } */ tempvar plotvalue varmiss qui egen `varmiss' = rowmiss(`varlist') if ("`continuoustreat'" != "" & "`type'" == "outcome") { cap gen `plotvalue' = 0 } else { if ("`ignoretreat'" != ""|"`type'" == "miss" | "`type'" == "missing") { if "`leavegap'" != "" { cap gen `plotvalue' = 0 if `varmiss' == 0 } else { cap gen `plotvalue' = 0 } } else { if ("`type'" == "outcome" & `numlevstreat' > 2) { cap gen `plotvalue' = 0 di "The number of treatment level is > 2; we ignore the treatment status." } else { //"`type'" == "treat" if "`leavegap'" != "" { cap gen `plotvalue' = `treat' if `varmiss' == 0 } else { cap gen `plotvalue' = `treat' } //remapping continuous treatment to 5 levels to fit color palettes levels: if "`continuoustreat'" != "" { qui sum `plotvalue' loc maxminplotvalue = r(max) - r(min) qui replace `plotvalue' = int((`plotvalue' - r(min)) * 4 / `maxminplotvalue' ) } } } } if ("`type'" == "miss" | "`type'" == "missing") { if ("`ignoretreat'" == "") { tempvar ignoretreat cap gen `ignoretreat' = 1 } } qui levelsof `plotvalue' if `touse', loc (levsplot) loc numlevsplot = r(r) if ("`ignoretreat'" == "") { if ("`continuoustreat'" == "" | "`type'" != "outcome") { if `numlevstreat' == 2 { if "`prepost'" != "" { foreach x of loc levsplot { qui replace `plotvalue' = `x' + 1 if `treat' == `x' & `treat' != 0 } qui replace `plotvalue' = 1 if `treat' == 0 & `gcontrol' == 0 //treated(pre) //levsplot: 0 <- control; 1 <- pre; 2 <- post qui levelsof `plotvalue' if `touse', loc (levsplot) loc numlevsplot = r(r) } } else if `numlevstreat' > 2 { if ("`type'" == "treat") { tempvar altlevsplot qui egen `altlevsplot' = group(`plotvalue') if `touse' cap replace `altlevsplot' = `altlevsplot' - 1 qui levelsof `altlevsplot' if `touse', loc (levsplot) loc numlevsplot = r(r) qui drop `altlevsplot' } } } } //deciding color if ("`type'" == "outcome") { colorpalette "198 219 239" "251 162 127" "red", n(`numlevsplot') nograph } else { colorpalette "198 219 239" "ebblue" "navy" "30 45 83" "black", n(`numlevsplot') nograph } if (`"`mycolor'"' != "") { colorpalette `mycolor' , n(`numlevsplot') nograph } if "`theme'" == "bw" { colorpalette Greys , n(`numlevsplot') nograph } if (`"`mycolor'"' != "Greys" & `"`mycolor'"' != "") { if ( "`theme'" == "bw") { di as err " If mycolor is not Greys, mycolor cannot combine with option theme(bw)" exit 198 } } qui return list tokenize `levsplot' loc trpreortr `2' tempvar nopre if "`trpreortr'" != "" { cap gen `nopre' = (`trpreortr' == 2) } else { cap gen `nopre' = 0 } if `nopre' != 1 { foreach w of loc levsplot { loc uu = `w' + 1 //012 -> 123 loc col`w' = r(p`uu') // colorpalette stores #th color in r(p#) } } else { foreach w of loc levsplot { if `w' == 0 { loc uu = `w' + 1 loc col`w' = r(p`uu') } else if `w' == 2 { loc col`w' = r(p`w') } } } if (`"`xlabel'"'=="") { qui sum `newtime', mean local xlabel `"xlabel(`r(min)'(`xlabdist')`r(max)', angle(90) nogrid labsize(tiny) valuelabel noticks)"' } if `"`bytiming'"' != "" { // With bytiming: if (`"`ylabel'"'=="") { qui sum `nids3', mean local ylabel `"ylabel(`r(min)'(`ylabdist')`r(max)', angle(0) nogrid labsize(tiny) valuelabel noticks)"' } } else { // Without bytiming: if (`"`ylabel'"'=="") { qui sum `nids', mean local ylabel `"ylabel(`r(min)'(`ylabdist')`r(max)', angle(0) nogrid labsize(tiny) valuelabel noticks)"' } } tempvar bgplotvalue labplotvalue qui bysort `nids': egen `bgplotvalue' = min(`plotvalue') qui levelsof `bgplotvalue' if `touse', loc (bglevsplot) label define `labplotvalue' 0 "Always Under Control" 1 "Treatment Status Changed" 2 "Always Treated" label val `bgplotvalue' `labplotvalue' if ("`type'" == "outcome") { //1. ploting outcome: type(outcome): if ("`discreteoutcome'" == "" ) { //continuous outcome //1.1. plotting lines of continuous outcome: qui tsset `nids' `tunit' qui drop if `tunit'==. tsfill, full tempvar stagger0 stagger qui by `nids': gen `stagger0' =1 if `treat'[_n]-`treat'[_n+1]==0 qui by `nids': replace `stagger0' =0 if `treat'[_n]-`treat'[_n+1]==1 qui egen `stagger' = min(`stagger0') loc staggersaclar=`stagger' if (`staggersaclar' == 0) { //treatment reversal: if ("`continuoustreat'" == "" & "`ignoretreat'" == "" & `numlevsplot'!=1){ di as err "continuous outcome lines cannot work with treatment reversals in Stata, please try the R version to make it" exit 198 } } di "now display lines of continuous outcome" loc lines1 if ("`bycohort'" == "" ) { foreach w of loc levsplot { foreach x of loc levsnids { if (`"`prepost'"' != "" & `w' == 1 ) { //with prepost: `w' == 1: treated(pre) if `islastchangedot' == 0 { loc lines1 `" `lines1' || line `outcome' `tunit' if `nids' == `x' & `gcontrol' == 0 & `touse', lcolor("`col`w''")"' } else{ loc lines1 `" `lines1' || line `outcome' `tunit' if `nids' == `x' & `gcontrol' == 0 & `touse', lcolor("`col`w''") || scatter `outcome' `tunit' if `nids' == `x' & `gcontrol' == 0 & `touse' & `lastchangedot' == 1, mcolor("`col`3''") msize(vsmall)"' } } else if (`"`prepost'"' == "" & `w' == 0 ) { //without prepost: `w' == 0: treated(pre) if `islastchangedot' == 0 { loc lines1 `" `lines1' || line `outcome' `tunit' if `nids' == `x' & `gcontrol' == 0 & `touse' , lcolor("`col`w''")"' } else{ loc lines1 `" `lines1' || line `outcome' `tunit' if `nids' == `x' & `gcontrol' == 0 & `touse', lcolor("`col`w''") || scatter `outcome' `tunit' if `nids' == `x' & `gcontrol' == 0 & `touse' & `lastchangedot' == 1, mcolor("`col`2''") msize(vsmall)"' } } loc lines1 `" `lines1' || line `outcome' `tunit' if `nids' == `x' & `plotvalue' == `w' & `touse' , lcolor("`col`w''")"' } } if ("`continuoustreat'" != "") { tw `lines1' legend(region(lstyle(none) fcolor(none)) order(1) label(1 "Observed") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } else { // not continuoustreat: if ("`ignoretreat'" != "" | `numlevsplot'==1) { // ignore treatment: tw `lines1' legend(region(lstyle(none) fcolor(none)) order(1) label(1 "Observed") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } else { if `numlevstreat' > 2 { tw `lines1' legend(region(lstyle(none) fcolor(none)) order(1) label(1 "Observed") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } else { // not ignore treatment: if ("`bygroup'" != "" ) { //with bygroup: if `islastchangedot' == 0 { tempvar allunits qui egen `allunits' = max(`nids') local largestlegend = 3*`allunits' + 1 local midlegend = 2*`allunits' if ("`bygroupside'" == "" ) { twoway `lines1' by(`bgplotvalue', note("") cols(1)) legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" `midlegend' "Treated (Pre)" `largestlegend' "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } else if ("`bygroupside'" != "" ) { twoway `lines1' by(`bgplotvalue', note("") rows(1)) legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" `midlegend' "Treated (Pre)" `largestlegend' "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } } else { tempvar allunits qui egen `allunits' = max(`nids') local largestlegend = `allunits' + 2 local midlegend = `allunits' + 1 if ("`bygroupside'" == "" ) { twoway `lines1' by(`bgplotvalue', note("") cols(1)) legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" `midlegend' "Treated (Pre)" `largestlegend' "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } else if ("`bygroupside'" != "" ) { twoway `lines1' by(`bgplotvalue', note("") rows(1)) legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" `midlegend' "Treated (Pre)" `largestlegend' "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } } } else{ //without bygroup: prepost=on: if (`"`prepost'"' != "") { if `islastchangedot' == 0 { tempvar allunits qui egen `allunits' = max(`nids') local largestlegend = 3*`allunits' + 1 local midlegend = 2*`allunits' tw `lines1' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" `midlegend' "Treated (Pre)" `largestlegend' "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } else { tempvar allunits qui egen `allunits' = max(`nids') local largestlegend = `allunits' + 2 local midlegend = `allunits' + 1 tw `lines1' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" `midlegend' "Treated (Pre)" `largestlegend' "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } } else { //prepost = off: if `islastchangedot' == 0 { tempvar allunits qui egen `allunits' = max(`nids') local largestlegend=3*`allunits' tw `lines1' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" `largestlegend' "Treated") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } else { tw `lines1' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" 2 "Treated") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) `options' } } } } } } } else if ("`bycohort'" != "" ) { * impute missing: ** expand to balanced panel: qui tsset `nids' `tunit' tsfill, full tempvar stagger0 stagger qui by `nids': gen `stagger0' =1 if `treat'[_n]-`treat'[_n+1]==0 qui by `nids': replace `stagger0' =0 if `treat'[_n]-`treat'[_n+1]==1 qui egen `stagger' = min(`stagger0') loc staggersaclar=`stagger' if `staggersaclar' == 1 { //staggered adoption: only allow dummy treatment qui bysort `nids' (`tunit'): replace `treat' = `treat'[_n-1] if `treat' == . gsort `nids' -`tunit' qui bysort `nids': replace `treat' = `treat'[_n-1] if `treat' == . sort `nids' `tunit' *qui bysort `nids' (`tunit'): replace `treat' = 1 if `treat' == . & `treat'[_n-1] == 1 *gsort `nids' -`tunit' *qui bysort `nids': replace `treat' = 0 if `treat' == . & `treat'[_n-1] == 0 *sort `nids' `tunit' } else if `staggersaclar' == 0 { //treatment reversal: di as err "option bycohort works only with staggered adoption" exit 198 } * graph: qui tostring `treat', replace tempvar history numhistorylevels qui bysort `nids' (`tunit'): generate `history' = `treat'[1] qui by `nids': replace `history' = `history'[_n-1] + `treat' if _n > 1 qui by `nids': replace `history' = `history'[_N] qui by `history', sort: gen `numhistorylevels' = _n == 1 *tab `history', m sort `nids' `tunit' *list in 1/180 qui count if `numhistorylevels' display "Number of unique treatment history: `r(N)'" if (`r(N)' > 20) { di as error "Option bycohort would not work if the number of unique treatment history is more than 20." exit 198 } else { // `r(N)' <= 20 tempvar outcomehistorymean historygroup qui egen `outcomehistorymean' = mean(`outcome'), by(`history' `tunit') qui replace `outcome' = `outcomehistorymean' qui egen `historygroup' = group(`history') qui levelsof `historygroup' if `touse', loc(historylevels) tempfile cohortlinehistory qui keep `outcome' `historygroup' `tunit' `gcontrol' `lastchangedot' `plotvalue' `touse' qui duplicates drop qui sum `tunit' qui replace `lastchangedot' = 0 if `tunit' != r(max) qui save `cohortlinehistory' foreach w of loc levsplot { //levsplot: 0 <- control; 1 <- pre; 2 <- post foreach x of loc historylevels { if (`"`prepost'"' != "" & `w' == 1 ) { //with prepost: `w' == 1: treated(pre) if `islastchangedot' == 0 { loc lines1 `" `lines1' || line `outcome' `tunit' if `historygroup' == `x' & `gcontrol' == 0 & `touse', lcolor("`col`w''")"' } else{ loc lines1 `" `lines1' || line `outcome' `tunit' if `historygroup' == `x' & `gcontrol' == 0 & `touse', lcolor("`col`w''") || scatter `outcome' `tunit' if `historygroup' == `x' & `gcontrol' == 0 & `touse' & `lastchangedot' == 1, mcolor("`col`3''") msize(vsmall)"' } } else if (`"`prepost'"' == "" & `w' == 0 ) { //without prepost: `w' == 0: treated(pre) if `islastchangedot' == 0 { loc lines1 `" `lines1' || line `outcome' `tunit' if `historygroup' == `x' & `gcontrol' == 0 & `touse', lcolor("`col`w''")"' } else { loc lines1 `" `lines1' || line `outcome' `tunit' if `historygroup' == `x' & `gcontrol' == 0 & `touse', lcolor("`col`w''") || scatter `outcome' `tunit' if `historygroup' == `x' & `gcontrol' == 0 & `touse' & `lastchangedot' == 1, mcolor("`col`2''") msize(vsmall)"' } } loc lines1 `" `lines1' || line `outcome' `tunit' if `historygroup' == `x' & `plotvalue' == `w' & `touse', lcolor("`col`w''")"' } } sort `tunit' if (`"`prepost'"' != "") { //with prepost: if `islastchangedot' == 0 { //no last changedot tempvar allunits qui egen `allunits' = max(`historygroup') local largestlegend = 3*`allunits' + 1 local midlegend = 2*`allunits' tw `lines1' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" `midlegend' "Treated (Pre)" `largestlegend' "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) ytitle("Cohort Average") title("Cohort Outcome Trajectories") `options' } else { //with last changedot tempvar allunits qui egen `allunits' = max(`historygroup') local largestlegend = `allunits' + 2 local midlegend = `allunits' + 1 tw `lines1' sort legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" `midlegend' "Treated (Pre)" `largestlegend' "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) ytitle("Cohort Average") title("Cohort Outcome Trajectories") `options' } } else { //prepost = off: if `islastchangedot' == 0 { //no last changedot tempvar allunits qui egen `allunits' = max(`historygroup') local largestlegend=3*`allunits' tw `lines1' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" `largestlegend' "Treated") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) ytitle("Cohort Average") title("Cohort Outcome Trajectories") `options' } else { //with last changedot tw `lines1' sort legend(region(lstyle(none) fcolor(none)) rows(1) order(1 "Control" 2 "Treated") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) ytitle("Cohort Average") title("Cohort Outcome Trajectories") `options' } } } } } else { //1.2. plotting dots of discrete outcome: //add some randomness to time units and outcome so that they can scatter around: * di "now display dots of discrete outcome" tempvar rout rtime cap gen `rtime' = `tunit' + runiform(-0.2, 0.2) cap gen `rout' = `outcome' + runiform(-0.2, 0.2) loc dot1 foreach w of loc levsplot { loc dot1 `" `dot1' || sc `rout' `rtime' if `plotvalue' == `w' & `touse' , mcolor("`col`w''") msize(small)"' } if ("`continuoustreat'" != "") { tw `dot1' legend(region(lstyle(none) fcolor(none)) row(1) order(1) label(1 "Observed") size(*0.8) symxsize(3) keygap(1)) ytitle("`outcome'") xtitle("`tunit'") `options' } else { if ("`ignoretreat'" != "" | `numlevsplot'==1) { // ignore treatment: tw `dot1' legend(region(lstyle(none) fcolor(none)) row(1) order(1) label(1 "Observed") size(*0.8) symxsize(3) keygap(1)) ytitle("`outcome'") xtitle("`tunit'") `options' } else { if `numlevstreat' > 2 { tw `dot1' legend(region(lstyle(none) fcolor(none)) row(1) order(1) label(1 "Observed") size(*0.8) symxsize(3) keygap(1)) ytitle("`outcome'") xtitle("`tunit'") `options' } else { // not ignore treatment: if ("`bygroup'" != "" ) { //with bygroup: if ("`bygroupside'" == "" ) { twoway `dot1' by(`bgplotvalue', cols(1) note("")) legend(region(lstyle(none) fcolor(none)) note("") row(1) label(1 "Control") label(2 "Treated (Pre)") label(3 "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) ytitle("`outcome'") xtitle("`tunit'") `options' } else if ("`bygroupside'" != "" ) { { twoway `dot1' by(`bgplotvalue', rows(1) note("")) legend(region(lstyle(none) fcolor(none)) note("") row(1) label(1 "Control") label(2 "Treated (Pre)") label(3 "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) ytitle("`outcome'") xtitle("`tunit'") `options' } } else{ //without bygroup: if (`"`prepost'"' != "") { tw `dot1' legend(region(lstyle(none) fcolor(none)) row(1) label(1 "Control") label(2 "Treated (Pre)") label(3 "Treated (Post)") size(*0.8) symxsize(3) keygap(1)) yscale(noline) xscale(noline) ytitle("`outcome'") xtitle("`tunit'") `options' } else { //prepost=off: tw `dot1' legend(region(lstyle(none) fcolor(none)) row(1) label(1 "Control") label(2 "Treated") size(*0.8) symxsize(3) keygap(1)) ytitle("`outcome'") xtitle("`tunit'") `options' } } } } } } } else if ("`type'" == "treat" | "`type'" == "miss" | "`type'" == "missing") { // 2. Heatmap of treatment: type(treat): di "Note: White cells represent missing values/observations in data." if `"`collapsehistory'"' == "" { if `"`bytiming'"' != "" { *2.1. With bytiming: tempvar y0 y1 cap gen `y1'=`nids3'+ 0.5 qui sum `y1' la val `y1' `:val lab `nids3'' cap gen `y0'=`nids3'- 0.5 qui levelsof `plotvalue' if `touse', loc(levsplot) qui sum `plotvalue' if `touse', mean if (`r(min)' < 0) { tempvar add cap gen `add' = 0 - `r(min)' cap replace `plotvalue' = `plotvalue' + `add' qui levelsof `plotvalue' if `touse', loc(levsplot_color) colorpalette "198 219 239" "107 174 214" "66 146 198" "31 120 180" "8 81 156" , n(`numlevsplot') nograph if (`"`mycolor'"' != "") { colorpalette `mycolor' , n(`numlevsplot') nograph } foreach w of loc levsplot_color { loc uu = `w' + 1 loc col`w' = r(p`uu') } foreach w of loc levsplot_color{ loc gcom `"`gcom'||rbar `y1' `y0' `newtime' if (`plotvalue'==`w')&(`touse'), barw(`xdist') col("`col`w''") fi(inten100) lw(none) "' } } else { foreach w of loc levsplot{ loc gcom `"`gcom'||rbar `y1' `y0' `newtime' if (`plotvalue'==`w')&(`touse'), barw(`xdist') col("`col`w''") fi(inten100) lw(none) "' } } loc sc `"sc `nids3' `newtime' if `touse', mlabpos(0) msy(i)"' } else { *2.2. Without bytiming: tempvar y0 y1 cap gen `y1'=`nids'+ 0.5 qui sum `y1' la val `y1' `:val lab `nidslab'' cap gen `y0'=`nids'- 0.5 qui levelsof `plotvalue' if `touse', loc(levsplot) qui sum `plotvalue' if `touse', mean if (`r(min)' < 0) { tempvar add cap gen `add' = 0 - `r(min)' cap replace `plotvalue' = `plotvalue' + `add' qui levelsof `plotvalue' if `touse', loc(levsplot_color) colorpalette "198 219 239" "107 174 214" "66 146 198" "31 120 180" "8 81 156" , n(`numlevsplot') nograph if (`"`mycolor'"' != "") { colorpalette `mycolor' , n(`numlevsplot') nograph } foreach w of loc levsplot_color { loc uu = `w' + 1 loc col`w' = r(p`uu') } foreach w of loc levsplot_color{ loc gcom `"`gcom'||rbar `y1' `y0' `newtime' if (`plotvalue'==`w')&(`touse'), barw(`xdist') col("`col`w''") fi(inten100) lw(none) "' //100% intensity, full color. Line has zero width: it vanishes } } else { foreach w of loc levsplot{ loc gcom `"`gcom'||rbar `y1' `y0' `newtime' if (`plotvalue'==`w')&(`touse'), barw(`xdist') col("`col`w''") fi(inten100) lw(none) "' //100% intensity, full color. Line has zero width: it vanishes } } loc sc `"sc `nids' `newtime' if `touse', mlabpos(0) msy(i)"' } if ("`ignoretreat'" != "" | `numlevsplot'==1) { // ignore treatment: local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1) label(1 "Observed") size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("`ids'") `ylabel' `xlabel' "' } else { // not ignore treatment: if `nopre' == 1 { local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2) label(1 "Control") label(2 "Treated") size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("`ids'") `ylabel' `xlabel' "' } else { if (`"`prepost'"' != "") { local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2 3) label(1 "Control") label(2 "Treated (Pre)") label(3 "Treated (Post)") size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("`ids'") `ylabel' `xlabel' "' } else { if "`continuoustreat'" != "" { qui sum `treat' loc maxminplotvalue = r(max) - r(min) loc dismaxminplotvalue = `maxminplotvalue' / 4 loc r_max = r(max) + `dismaxminplotvalue' tempvar plotvalue1 qui egen `plotvalue1' = cut(`treat'), at(`r(min)' (`dismaxminplotvalue') `r_max') qui levelsof `plotvalue1' if `touse', loc (levsplot1) tokenize `levsplot1' loc contrlev1 `1' loc contrlev2 `2' loc contrlev3 `3' loc contrlev4 `4' loc contrlev5 `5' loc contrlev11=round(`1', 0.001) loc contrlev22=round(`2', 0.001) loc contrlev33=round(`3', 0.001) loc contrlev44=round(`4', 0.001) loc contrlev55=round(`5', 0.001) if `contrlev55' > `contrlev44' { local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2 3 4 5) label(1 "`contrlev11'") label(2 "`contrlev22'") label(3 "`contrlev33'") label(4 "`contrlev44'") label(5 "`contrlev55'") title("Treatment levels: ", size(*0.45)) size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("`ids'") `ylabel' `xlabel' "' } else { local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2 3 4) label(1 "`contrlev11'") label(2 "`contrlev22'") label(3 "`contrlev33'") label(4 "`contrlev44'") title("Treatment level: ", size(*0.45)) size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("`ids'") `ylabel' `xlabel' "' } } else { if `numlevstreat' > 2 { tokenize `levsplot' loc trlev1 `1' loc trlev2 `2' loc trlev3 `3' loc trlev4 `4' // If the number of treatment levels >= 5, need to combine with Continuoustreat if "`trlev4'" != ""{ //treatment levels = 4: local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(2) order(1 2 3 4) label(1 "Treatment level: `trlev1'") label(2 "Treatment level: `trlev2'") label(3 "Treatment level: `trlev3'") label(4 "Treatment level: `trlev4'") size(*0.55) symxsize(3) keygap(0.5) colgap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("`ids'") `ylabel' `xlabel' "' } else { //treatment levels = 3: local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2 3) label(1 "Treatment level: `trlev1'") label(2 "Treatment level: `trlev2'") label(3 "Treatment level: `trlev3'") size(*0.55) symxsize(3) keygap(0.5) colgap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("`ids'") `ylabel' `xlabel' "' } } else { //treatment levels = 2: local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2) label(1 "Control") label(2 "Treated") size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("`ids'") `ylabel' `xlabel' "' } } } } } tw `gcom' plotr(fc(white) margin(zero)) ||`sc' `options' } else if `"`collapsehistory'"' != "" { // with collapsehistory qui tostring `treat', replace tempvar history numhistorylevels historymember qui bysort `nids' (`tunit'): generate `history' = `treat'[1] qui by `nids': replace `history' = `history'[_n-1] + `treat' if _n > 1 qui by `nids': replace `history' = `history'[_N] qui by `history', sort: gen `numhistorylevels' = _n == 1 qui bysort `history' `nids': gen `historymember'= _n == 1 qui by `history': replace `historymember' = sum(`historymember') qui by `history': replace `historymember' = `historymember'[_N] *tab `history', m *tab `history', m sort tempvar historygroup qui egen `historygroup' = group(`history') *tab `historygroup', m *tab `historygroup', m sort tempvar labelhistorymember qui tostring `historymember', gen(`labelhistorymember') labmask `historygroup', val(`labelhistorymember') qui count if `numhistorylevels' display "Number of unique treatment history: `r(N)'" tempfile cohortlinehistory qui keep `treat' `historygroup' `historymember' `newtime' `lastchangedot' `plotvalue' `touse' `nopre' qui duplicates drop gsort -`historymember' `historygroup' `newtime' *list qui sum `newtime' qui replace `lastchangedot' = 0 if `newtime' != r(max) *list in 1/120 qui save `cohortlinehistory' //i: historygroup; t: newtime qui sum `historygroup', mean local ylabel `"ylabel(`r(min)'(1)`r(max)', alternate angle(0) nogrid labsize(tiny) valuelabel noticks)"' tempvar y0 y1 cap gen `y1'=`historygroup'+ 0.5 qui sum `y1' la val `y1' `:val lab `historygroup'' cap gen `y0'=`historygroup'- 0.5 qui levelsof `plotvalue' if `touse', loc(levsplot) qui sum `plotvalue' if `touse', mean if (`r(min)' < 0) { tempvar add cap gen `add' = 0 - `r(min)' cap replace `plotvalue' = `plotvalue' + `add' qui levelsof `plotvalue' if `touse', loc(levsplot_color) colorpalette "198 219 239" "107 174 214" "66 146 198" "31 120 180" "8 81 156" , n(`numlevsplot') nograph if (`"`mycolor'"' != "") { colorpalette `mycolor' , n(`numlevsplot') nograph } foreach w of loc levsplot_color { loc uu = `w' + 1 loc col`w' = r(p`uu') } foreach w of loc levsplot_color{ loc gcom `"`gcom'||rbar `y1' `y0' `newtime' if (`plotvalue'==`w')&(`touse'), barw(`xdist') col("`col`w''") fi(inten100) lw(none) "' } } else { foreach w of loc levsplot{ loc gcom `"`gcom'||rbar `y1' `y0' `newtime' if (`plotvalue'==`w')&(`touse'), barw(`xdist') col("`col`w''") fi(inten100) lw(none) "' } } loc sc `"sc `historygroup' `newtime' if `touse', mlabpos(0) msy(i)"' if `nopre' == 1 { local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2) label(1 "Control") label(2 "Treated") size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("Number of `ids'") `ylabel' `xlabel' "' } else { if (`"`prepost'"' != "") { local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2 3) label(1 "Control") label(2 "Treated (Pre)") label(3 "Treated (Post)") size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("Number of `ids'") `ylabel' `xlabel' "' } else { if "`continuoustreat'" != "" { qui sum `treat' loc maxminplotvalue = r(max) - r(min) loc dismaxminplotvalue = `maxminplotvalue' / 4 loc r_max = r(max) + `dismaxminplotvalue' tempvar plotvalue1 qui egen `plotvalue1' = cut(`treat'), at(`r(min)' (`dismaxminplotvalue') `r_max') qui levelsof `plotvalue1' if `touse', loc (levsplot1) tokenize `levsplot1' loc contrlev1 `1' loc contrlev2 `2' loc contrlev3 `3' loc contrlev4 `4' loc contrlev5 `5' loc contrlev11=round(`1', 0.001) loc contrlev22=round(`2', 0.001) loc contrlev33=round(`3', 0.001) loc contrlev44=round(`4', 0.001) loc contrlev55=round(`5', 0.001) if `contrlev55' > `contrlev44' { local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2 3 4 5) label(1 "`contrlev11'") label(2 "`contrlev22'") label(3 "`contrlev33'") label(4 "`contrlev44'") label(5 "`contrlev55'") title("Treatment levels: ", size(*0.45)) size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("Number of `ids'") `ylabel' `xlabel' "' } else { local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2 3 4) label(1 "`contrlev11'") label(2 "`contrlev22'") label(3 "`contrlev33'") label(4 "`contrlev44'") title("Treatment level: ", size(*0.45)) size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("Number of `ids'") `ylabel' `xlabel' "' } } else { if `numlevstreat' > 2 { tokenize `levsplot' loc trlev1 `1' loc trlev2 `2' loc trlev3 `3' loc trlev4 `4' // If the number of treatment levels >= 5, need to combine with Continuoustreat if "`trlev4'" != ""{ //treatment levels = 4: local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(2) order(1 2 3 4) label(1 "Treatment level: `trlev1'") label(2 "Treatment level: `trlev2'") label(3 "Treatment level: `trlev3'") label(4 "Treatment level: `trlev4'") size(*0.55) symxsize(3) keygap(0.5) colgap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("Number of `ids'") `ylabel' `xlabel' "' } else { //treatment levels = 3: local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2 3) label(1 "Treatment level: `trlev1'") label(2 "Treatment level: `trlev2'") label(3 "Treatment level: `trlev3'") size(*0.55) symxsize(3) keygap(0.5) colgap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("Number of `ids'") `ylabel' `xlabel' "' } } else { //treatment levels = 2: local gcom `"`gcom' legend(region(lstyle(none) fcolor(none)) rows(1) order(1 2) label(1 "Control") label(2 "Treated") size(*0.6) symxsize(3) keygap(1)) xsize(2) ysize(2) yscale(noline reverse) xscale(noline) aspect(1) xtitle("`tunit'") ytitle("Number of `ids'") `ylabel' `xlabel' "' } } } } tw `gcom' plotr(fc(white) margin(zero)) ||`sc' `options' } } else if ("`type'" == "bivar" | "`type'" == "bivariate"){ if (`"`mycolor'"' != "") { colorpalette `mycolor' , n(2) nograph loc y2color = r(p1) loc y1color = r(p2) } else { loc y1color = "0 0 0" loc y2color = "144 144 144" } if ("`lwd'" == "") { loc linewide = "medium" } else { loc linewide = "`lwd'" } if ("`style'" == "") { if ("`discreteoutcome'" == "" & "`continuoustreat'" == "") { //continuous Y, discrete D loc style = "l b" } else if ("`discreteoutcome'" != "" & "`continuoustreat'" == "") { //discrete Y, discrete D loc style = "b b" } else if ("`discreteoutcome'" == "" & "`continuoustreat'" != "") { //continuous Y, continuous D loc style = "l l" } else if ("`discreteoutcome'" != "" & "`continuoustreat'" != "") { //discrete Y, continuous D loc style = "b l" } } else if ("`style'" != "") { if ("`style'" == "l" | "`style'" == "line") { loc style = "l l" } else if ("`style'" == "b" | "`style'" == "bar") { loc style = "b b" } else if ("`style'" == "c" | "`style'" == "connected") { loc style = "c c" } } qui sum `newtime', mean local xlabel `"xlabel(`r(min)'(`xlabdist')`r(max)', valuelabel)"' qui levelsof `treat' if `touse' , loc (levstreat) qui levelsof `outcome' if `touse' , loc (levsoutcome) if "`byunit'" == "" { // 3.1 Plot D and Y against time in the same graph (average D and Y by year): collapse (mean) `outcome' `treat', by(`newtime') if ("`style'" == "l b"|"`style'" == "line bar"|"`style'" == "line b"|"`style'" == "l bar") { twoway line `outcome' `newtime', `xlabel' yaxis(1) color("`y1color'") lw(`linewide') `options' /// || bar `treat' `newtime', yaxis(2) color("`y2color'%50") xtitle("") `options' /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) } else if ("`style'" == "l l"|"`style'" == "line line"|"`style'" == "line l"|"`style'" == "l line") { twoway line `outcome' `newtime', `xlabel' yaxis(1) color("`y1color'") lw(`linewide') `options' /// || line `treat' `newtime', yaxis(2) color("`y2color'") xtitle("") lw(`linewide') `options' /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) } else if ("`style'" == "b l"|"`style'" == "bar line"|"`style'" == "bar l"|"`style'" == "b line") { twoway bar `outcome' `newtime', `xlabel' yaxis(1) color("`y1color'%20") `options' /// || line `treat' `newtime', yaxis(2) color("`y2color'") xtitle("") lw(`linewide') `options' /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) } else if ("`style'" == "b b"|"`style'" == "bar bar"|"`style'" == "bar b"|"`style'" == "b bar") { twoway bar `outcome' `newtime', `xlabel' yaxis(1) color("`y1color'%50") `options' /// || bar `treat' `newtime', yaxis(2) color("`y2color'%50") xtitle("") `options' /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) } else if ("`style'" == "c b"|"`style'" == "connected bar"|"`style'" == "connected b"|"`style'" == "c bar") { twoway connected `outcome' `newtime', `xlabel' yaxis(1) color("`y1color'") lw(`linewide') `options' /// || bar `treat' `newtime', yaxis(2) color("`y2color'%50") xtitle("") `options' /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) } else if ("`style'" == "c c"|"`style'" == "connected connected"|"`style'" == "connected c"|"`style'" == "c connected") { twoway connected `outcome' `newtime', `xlabel' yaxis(1) color("`y1color'") lw(`linewide') `options' /// || connected `treat' `newtime', yaxis(2) color("`y2color'") xtitle("") lw(`linewide') `options' /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) } else if ("`style'" == "b c"|"`style'" == "bar connected"|"`style'" == "bar c"|"`style'" == "b connected") { twoway bar `outcome' `newtime', `xlabel' yaxis(1) color("`y1color'%20") `options' /// || connected `treat' `newtime', yaxis(2) color("`y2color'") xtitle("") lw(`linewide') `options' /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) } else if ("`style'" == "l c"|"`style'" == "line connected"|"`style'" == "line c"|"`style'" == "l connected") { twoway line `outcome' `newtime', `xlabel' yaxis(1) color("`y1color'") lw(`linewide') `options' /// || connected `treat' `newtime', yaxis(2) color("`y2color'") xtitle("") lw(`linewide') `options' /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) } else if ("`style'" == "c l"|"`style'" == "connected line"|"`style'" == "connected l"|"`style'" == "c line") { twoway connected `outcome' `newtime', `xlabel' yaxis(1) color("`y1color'") lw(`linewide') `options' /// || line `treat' `newtime', yaxis(2) color("`y2color'") xtitle("") lw(`linewide') `options' /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) } } else { // 3.2 Plot D and Y against time in the same graph by each unit: cap label list `i' if "`r(k)'" == "" { tempvar labeli qui tostring `i', gen(`labeli') labmask `i', val(`labeli') } qui levelsof `ids' if `touse' , loc (levsids) local graphs "" if ("`discreteoutcome'" == "" & "`continuoustreat'" == "") { //continuous Y, discrete D foreach x of loc levsids { local lx: label (`i') `x' qui levelsof `treat' if `touse' , loc (levstreat) if ("`style'" == "l b"|"`style'" == "line bar"|"`style'" == "line b"|"`style'" == "l bar") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' /// ||, ylabel(`levstreat', valuelabel axis(2)) ytitle("",axis(2)) xtitle("") title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "l l"|"`style'" == "line line"|"`style'" == "line l"|"`style'" == "l line") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, ylabel(`levstreat', valuelabel axis(2)) ytitle("",axis(2)) xtitle("") title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b l"|"`style'" == "bar line"|"`style'" == "bar l"|"`style'" == "b line") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%20") lw(none) `xlabel' ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, ylabel(`levstreat', valuelabel axis(2)) ytitle("",axis(2)) xtitle("") title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b b"|"`style'" == "bar bar"|"`style'" == "bar b"|"`style'" == "b bar") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%50") lw(none) `xlabel' ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' /// ||, ylabel(`levstreat', valuelabel axis(2)) ytitle("",axis(2)) xtitle("") title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c b"|"`style'" == "connected bar"|"`style'" == "connected b"|"`style'" == "c bar") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' /// ||, ylabel(`levstreat', valuelabel axis(2)) ytitle("",axis(2)) xtitle("") title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c c"|"`style'" == "connected connected"|"`style'" == "connected c"|"`style'" == "c connected") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, ylabel(`levstreat', valuelabel axis(2)) ytitle("",axis(2)) xtitle("") title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b c"|"`style'" == "bar connected"|"`style'" == "bar c"|"`style'" == "b connected") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%20") lw(none) `xlabel' ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, ylabel(`levstreat', valuelabel axis(2)) ytitle("",axis(2)) xtitle("") title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "l c"|"`style'" == "line connected"|"`style'" == "line c"|"`style'" == "l connected") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, ylabel(`levstreat', valuelabel axis(2)) ytitle("",axis(2)) xtitle("") title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c l"|"`style'" == "connected line"|"`style'" == "connected l"|"`style'" == "c line") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, ylabel(`levstreat', valuelabel axis(2)) ytitle("",axis(2)) xtitle("") title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } } } else if ("`discreteoutcome'" != "" & "`continuoustreat'" == "") { //discrete Y, discrete D foreach x of loc levsids { local lx: label (`i') `x' qui levelsof `treat' if `touse' , loc (levstreat) qui levelsof `outcome' if `touse' , loc (levsoutcome) if ("`style'" == "l b"|"`style'" == "line bar"|"`style'" == "line b"|"`style'" == "l bar") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' ylabel(`levstreat', valuelabel axis(2)) /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "l l"|"`style'" == "line line"|"`style'" == "line l"|"`style'" == "l line") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') ylabel(`levstreat', valuelabel axis(2)) /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b l"|"`style'" == "bar line"|"`style'" == "bar l"|"`style'" == "b line") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%20") lw(none) `xlabel' ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') ylabel(`levstreat', valuelabel axis(2)) /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b b"|"`style'" == "bar bar"|"`style'" == "bar b"|"`style'" == "b bar") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%50") lw(none) `xlabel' ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' ylabel(`levstreat', valuelabel axis(2)) /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c b"|"`style'" == "connected bar"|"`style'" == "connected b"|"`style'" == "c bar") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' ylabel(`levstreat', valuelabel axis(2)) /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c c"|"`style'" == "connected connected"|"`style'" == "connected c"|"`style'" == "c connected") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') ylabel(`levstreat', valuelabel axis(2)) /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b c"|"`style'" == "bar connected"|"`style'" == "bar c"|"`style'" == "b connected") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%20") lw(none) `xlabel' ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') ylabel(`levstreat', valuelabel axis(2)) /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "l c"|"`style'" == "line connected"|"`style'" == "line c"|"`style'" == "l connected") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') ylabel(`levstreat', valuelabel axis(2)) /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c l"|"`style'" == "connected line"|"`style'" == "connected l"|"`style'" == "c line") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') ylabel(`levstreat', valuelabel axis(2)) /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } } } else if ("`discreteoutcome'" == "" & "`continuoustreat'" != "") { //continuous Y, continuous D foreach x of loc levsids { local lx: label (`i') `x' if ("`style'" == "l b"|"`style'" == "line bar"|"`style'" == "line b"|"`style'" == "l bar") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "l l"|"`style'" == "line line"|"`style'" == "line l"|"`style'" == "l line") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b l"|"`style'" == "bar line"|"`style'" == "bar l"|"`style'" == "b line") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%20") lw(none) `xlabel' ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b b"|"`style'" == "bar bar"|"`style'" == "bar b"|"`style'" == "b bar") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%50") lw(none) `xlabel' ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c b"|"`style'" == "connected bar"|"`style'" == "connected b"|"`style'" == "c bar") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c c"|"`style'" == "connected connected"|"`style'" == "connected c"|"`style'" == "c connected") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b c"|"`style'" == "bar connected"|"`style'" == "bar c"|"`style'" == "b connected") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%20") lw(none) `xlabel' ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "l c"|"`style'" == "line connected"|"`style'" == "line c"|"`style'" == "l connected") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c l"|"`style'" == "connected line"|"`style'" == "connected l"|"`style'" == "c line") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } } } else if ("`discreteoutcome'" != "" & "`continuoustreat'" != "") { //discrete Y, continuous D foreach x of loc levsids { local lx: label (`i') `x' qui levelsof `outcome' if `touse' , loc (levsoutcome) /* twoway `lineordot' `outcome' `newtime' if `ids' == `x', yaxis(1) ylabel(`levsoutcome', valuelabel axis(1)) color("`y1color'") `xlabel' lw(`linewide') /// || `lineordot' `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw local graphs "`graphs' graph_`x'" */ if ("`style'" == "l b"|"`style'" == "line bar"|"`style'" == "line b"|"`style'" == "l bar") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "l l"|"`style'" == "line line"|"`style'" == "line l"|"`style'" == "l line") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b l"|"`style'" == "bar line"|"`style'" == "bar l"|"`style'" == "b line") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%20") lw(none) `xlabel' ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b b"|"`style'" == "bar bar"|"`style'" == "bar b"|"`style'" == "b bar") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%50") lw(none) `xlabel' ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c b"|"`style'" == "connected bar"|"`style'" == "connected b"|"`style'" == "c bar") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || bar `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'%50") lw(none) `xlabel' /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c c"|"`style'" == "connected connected"|"`style'" == "connected c"|"`style'" == "c connected") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "b c"|"`style'" == "bar connected"|"`style'" == "bar c"|"`style'" == "b connected") { twoway bar `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'%20") lw(none) `xlabel' ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "l c"|"`style'" == "line connected"|"`style'" == "line c"|"`style'" == "l connected") { twoway line `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || connected `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } else if ("`style'" == "c l"|"`style'" == "connected line"|"`style'" == "connected l"|"`style'" == "c line") { twoway connected `outcome' `newtime' if `ids' == `x', yaxis(1) color("`y1color'") `xlabel' lw(`linewide') ylabel(`levsoutcome', valuelabel axis(1)) ytitle("") /// || line `treat' `newtime' if `ids' == `x', yaxis(2) color("`y2color'") `xlabel' lw(`linewide') /// ||, xtitle("") ytitle("",axis(2)) title("`lx'") name(graph_`x', replace) nodraw /// legend(region(lstyle(none) fcolor(none)) rows(1) size(*0.8) symxsize(3)) local graphs "`graphs' graph_`x'" } } } tokenize graphs loc graph_1 `2' grc1leg `graphs', legendfrom(`graph_1') ycommon cols(4) l1title(`outcome') r1title(`treat') `options' } } restore end