/* CREATED: 8 Sep 2017 AUTHOR: Victoria N Nyaga PURPOSE: Generalized linear fixed, mixed & random effects modelling of binomial data. VERSION: 3.0.2 NOTES 1. Variable names and group names should not contain underscore(_) 2. Data should be sorted and no duplicates ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UPDATES ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DATE: DETAILS: 24.08.2020 grid: Grid lines between studies noveral in help file changed to noOVerall Print full matrix of rr when data is not repeated Print # of studies Correct the tick & axis position for sp Correct computation of the I2 graphsave(filename) option included 03.09.2020 Change paired to comparative 14.19.2020 Correct way of counting the distinct groups in the meta-analysis Check to ensure variable names do no contain underscore. 12.02.2021 paired data: a b c d comparator index covariates, by(byvar) comparator, index, byvar need to be string Need to test more with more covariates!!! 09.07.2021 cimodel > cimethod Overal isq not showing with dp>2 01.02.2022 Change paired to matched paired data: n1 n2 N comparator index covariates, by(byvar) Subgroup analysis with superimposed graphs; stratify option stratify not an option for paired, matched or network 15.03.2022 design(independent|matched|paired|comparative|network, baselevel(string)) network data: n N Assignment covariates ....repeated measurements per study 27.05.2022 Corrections on absoutp stratify + comparative + outplot(RR) 11.02.2023 change network to abnetwork, paired to pcbnetwork, matched to mcbnetwork Work on: hetout, stratify marginal results with 1 study 07.03.2023 change independent to general 21.03.2023 Compute weights from the maximized log likelihood Exact inference in few studies 18.04.2023 Use t-distribution for summaries 05.06.2023 Simulate posterior distributions smooth:Option to generate smooth estimates 26.07.2023 if version 16; use melogit instead of meqrlogit 20.09.2023 Include outplot(OR) 23.10.2023 nsims;how many times to simulate the posterior distributions 31.10.2023 clolog ink (might be better if p > .9) lolog ink (might be better if p < .1) */ /*++++++++++++++++++++++ METAPREG +++++++++++++++++++++++++++++++++++++++++++ WRAPPER FUNCTION +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop metapreg program define metapreg, eclass sortpreserve byable(recall) version 14.1 #delimit ; syntax varlist(min=2) [if] [in], STudyid(varname) [ ALphasort AStext(integer 50) CImethod(string) //i=[wald, exact, score], o=[wald, exact, score, t] CIOpts(string) DIAMopts(string) DOUBLE GOF //Goodness of fit DOWNload(string asis) DP(integer 2) Level(integer 95) INTeraction LABEL(string) LCols(varlist) Model(string) //model(random|mixed|fixed|hexact, options) noGRaph noOVerall noOVLine noSTats noSUBgroup noITAble noWT noBox SMooth nsims(integer 800) //max dim in stata ic OLineopts(string) outplot(string) //abs|rr|or SUMTable(string) //none|logit|abs|rr|all DESign(string) //design(general|matched-mcbnetwork|paired-pcbnetwork|comparative|network-abnetwork, baselevel(string) | cov(inde|unstr)) POINTopts(string) BOXopts(string) POwer(integer 0) PREDciOpt(string) RCols(varlist) PREDIction //prediction SORtby(varlist) SUBLine SUMMARYonly SUMStat(string asis) TEXts(real 1.0) XLAbel(passthru) XLIne(passthru) /*silent option*/ XTick(passthru) noMC /*No Model comparison - Saves time*/ PROGress /*See the model fitting*/ graphsave(string) by(varname) STRatify /*Stratified analysis, requires byvar()*/ logscale link(string) /*logit|cloglog|loglog*/ *] ; #delimit cr preserve marksample touse, strok qui drop if !`touse' tempvar rid event nonevent total invtotal use id neolabel /// es se lci uci grptotal uniq mu use rid lpi upi obsid /// modeles modellci modeluci tempname nltestRR nltestOR mctest samtrix logodds rrout orout absout logoddsi orouti rrouti absouti /// coefmat coefvar BVar WVar omat isq2 bghet bshet lrtestp V dftestnl ptestnl lrtest /// outr absoutp absoutpi hetout hetouti popabsout popabsouti poprrout poprrouti poporout poporouti poplorout poplorouti /*Check for mu; its reserved*/ qui ds local vlist = r(varlist) foreach v of local vlist { if "`v'" == "mu" { di in re "mu is a reserved variable name; drop or rename mu" exit _rc } } qui { cap gen mu = 1 cap gen _ESAMPLE = 0 cap drop _WT gen _WT = . cap gen `modeles' = . cap gen `modellci' = . cap gen `modeluci' = . } //Check link if "`link'" == "" { local link "logit" } else { if strpos("`link'", "cl") != 0 { local link "cloglog" } else if strpos("`link'", "logl") != 0 { local link "loglog" } else if strpos("`link'", "logi") != 0 { local link "logit" } else { di as error "The link `link' not allowed." exit } } if _by() { global by_index_ = _byindex() if "`graph'" == "" & "$by_index_" == "1" { cap graph drop _all } } else { global by_index_ } if "`design'" == "" { local design = "general" } else { tokenize "`design'", parse(",") local design `1' //options local desopts "`3'" while "`desopts'" != "" { gettoken option desopts : desopts macro shift if strpos("`option'", "base") != 0 { local baselevel "`option'" } else if strpos("`option'", "cov") != 0 { local cov "`option'" } else { di as error "`option' not allowed in specifying the design()" exit } } if "`cov'" != "" { cap assert ("`design'" == "comparative") if _rc!=0 { di as error "The option `cov' only allowed in comparative meta-analysis" exit } if strpos("`cov'", "ind") !=0 { local cov "independent" } else if strpos("`cov'", "unst") !=0 { local cov "unstructured" } else { di as error "`cov' not allowed in specifying the design()" exit } } } //depracated options if "`design'" == "paired" { di as res "Use of the option -design(paired)- is deprecated and replaced with -design(pcbnetwork)-" local design "pcbnetwork" } if "`design'" == "matched" { di as res "Use of the option -design(matched)- is deprecated and replaced with -design(mcbnetwork)-" local design "mcbnetwork" } if "`design'" == "network" { di as res "Use of the option -design(network)- is deprecated and replaced with -design(abnetwork)-" local design "abnetwork" } if ("`design'" == "mcbnetwork") | ("`design'" == "pcbnetwork") { tempvar index byvar assignment idpair ipair } local fopts `"`options'"' /*Check if variables exist*/ foreach var of local varlist { cap confirm var `var' if _rc!=0 { di in re "Variable `var' not in the dataset" exit _rc } } //General housekeeping //Mixed or random are synonym if "`model'" == "" { local model random } else { tokenize "`model'", parse(",") local model `1' local modelopts "`3'" } if strpos("`model'", "f") == 1 { local model "fixed" } else if (strpos("`model'", "r") == 1) | (strpos("`model'", "m") == 1) { local model "random" } else if strpos("`model'", "h") == 1 { local model "hexact" } else { di as error "Invalid option `model'" di as error "Specify either fixed, random, mixed, or hexact" exit } if "`model'" == "fixed" & strpos("`modelopts'", "ml") != 0 { di as error "Option ml not allowed in `modelopts'" exit } if "`model'" == "fixed" & strpos("`modelopts'", "irls") != 0 { di as error "Option irls not allowed in `modelopts'" exit } //Avoid Incosistencies & Redundancies if "`stratify'" != "" & "`summaryonly'" != "" { local wt nowt } //Graph options if "`summaryonly'" != "" { local box "nobox" } if "`outplot'" == "abs" & "`design'" == "comparative" & "`model'" == "fixed" { local design "general" } qui count if `=r(N)' < 2 { di as err "Insufficient data to perform meta-analysis" exit } if `=r(N)' < 3 & "`model'" != "hexact" { local model hexact //If less than 3 studies, use exact di as res _n "Note: Homo-exact model imposed whenever number of studies is less than 3." if "`modelopts'" != "" { local modelopts di as res _n "Warning: Model options ignored." di as res _n "Warning: Consider re-specifying options for the fixed-effects model should the model not converge." } } if `level'<1 { local level `level'*100 } if `level'>99 | `level'<10 { local level 95 } if `astext'>99 | `astext' <1 { local astext 50 } //Number of studies in the analysis cap assert "`studyid'" != "" if _rc!=0 { di as err "The study identifier variable is not specified" di as err "Specify it with STUDYID(varname) " exit _rc } tokenize `varlist' if "`design'" == "general" | "`design'" == "comparative" | "`design'" == "abnetwork" { gen `total' = `2' gen `event' = `1' gen `nonevent' = `total' - `event' forvalues num = 1/2 { cap confirm integer number `num' if _rc != 0 { di as error "`num' found where integer expected" exit } } cap assert `total' >= `event' if (`event' ~= .) if _rc != 0 { di as err "Order should be {n N}. Check your data." exit _rc } local depvars "`1' `2'" macro shift 2 } else if "`design'" == "mcbnetwork" { local a = "`1'" local b = "`2'" local c = "`3'" local d = "`4'" cap assert "`6'" != "" if _rc != 0 { di as err "mcbnetwork data requires atleast 6 variable" exit _rc } local depvars "`1' `2' `3' `4'" local Comparator = "`6'" local Index = "`5'" forvalues num = 1/4 { cap confirm integer number `num' if _rc != 0 { di as error "`num' found where integer expected" exit } } cap confirm string variable `5' if _rc != 0 { di as error "The first & second covariate in cbnetwork analysis should be a string" exit _rc } cap confirm string variable `6' if _rc != 0 { di as error "The first & second covariate in cbnetwork analysis should be a string" exit _rc } macro shift 6 } else if "`design'" == "pcbnetwork" { local event1 = "`1'" local event2 = "`2'" local Total = "`3'" cap assert "`5'" != "" if _rc != 0 { di as err "pcbnetwork data requires atleast 5 variable" exit _rc } local depvars "`1' `2' `3'" local Comparator = "`5'" local Index = "`4'" cap assert ((`Total' >= `event1') & (`Total' >= `event2')) if ((`event1' ~= .) & (`event2' ~= .)) if _rc != 0 { di as err "Order should be {n1 n2 N}. Check your data." exit _rc } forvalues num = 1/3 { cap confirm integer number `num' if _rc != 0 { di as error "`num' found where integer expected" exit } } cap confirm string variable `4' if _rc != 0 { di as error "The first & second covariate in pcbnetwork analysis should be a string" exit _rc } cap confirm string variable `5' if _rc != 0 { di as error "The first & second covariate in pcbnetwork analysis should be a string" exit _rc } macro shift 5 } local regressors "`*'" local p: word count `regressors' if "`model'" == "hexact" { cap assert `p' == 0 if _rc != 0 { di as error "Covariates not allowed in the `model' model. Specify model(fixed) or model(mixed)" exit _rc } } if "`design'" == "comparative" | "`design'" == "abnetwork" { if "`model'" != "fixed" { cap assert `p' > 0 if _rc != 0 { di as error "`design' analysis requires at least 1 covariate to be specified" exit _rc } } else { cap assert `p' > 1 if _rc != 0 { di as error "`design' analysis requires at least 2 covariate to be specified" exit _rc } } } if "`design'" == "comparative" | "`design'" == "abnetwork" { gettoken first confounders : regressors if "`first'" != "" { cap confirm string variable `first' if _rc != 0 { di as error "The first covariate in `design' analysis should be a string" exit _rc } } cap assert ("`first'" != "`by'") & ("`output'" != "rr") if _rc != 0 { di as error "Remove the option by(`by') or specify a different by-variable" exit _rc } } if "`outplot'" == "" { local outplot = "abs" } else { if "`outplot'" == "rr" | "`outplot'" == "or" { cap assert "`design'" != "general" if _rc != 0 { di as error "Option outplot(`outplot') only avaialable for comparative/mcbnetwork/pcbnetwork/abnetwork designs with first covariate as string" di as error "Specify the first string covariate and the appropriate design(comparative/mcbnetwork/pcbnetwork/abnetwork)" exit _rc } } } if ("`design'" == "mcbnetwork" | "`design'" == "pcbnetwork") & ("`outplot'" != "or" ) { local outplot = "rr" } cap assert ("`outplot'" == "rr") | ("`outplot'" == "or") | ("`outplot'" == "abs") if _rc != 0 { di as error "Invalid option in outplot(`outplot')" exit _rc } if "`sumstat'" == "" { if "`outplot'" == "abs" { local sumstat = "Proportion" } else if "`outplot'" == "rr" { local sumstat = "Proportion Ratio" } else if "`outplot'" == "or" { local sumstat = "Odds Ratio" } } //CI method /*if "`outplot'" == "rr" { if "`cimethod'" != "" { local ocimethod "`cimethod'" if (strpos("`ocimethod'", "t") != 1) & (strpos("`ocimethod'", "w") != 1){ di as error "Option `ocimethod' not allowed in cimethod(`cimethod')" exit } } else { local ocimethod "wald" } if "`design'" == "mcbnetwork" { local icimethod "CML" } if "`design'" == "pcbnetwork" | "`design'" == "comparative" { local icimethod "Koopman" } }*/ if "`outplot'" != "abs" { if "`cimethod'" != "" & (strpos("`cimethod'", ",") != 1) { tokenize "`cimethod'", parse(",") local icimethod "`1'" if "`3'" != "" { local ocimethod = strltrim("`3'") } } if "`cimethod'" != "" & (strpos("`cimethod'", ",") == 1) { tokenize "`cimethod'", parse(",") if "`2'" != "" { local ocimethod = strltrim("`2'") } } //iOR if ("`icimethod'" != "") & "`outplot'" == "or" { if (strpos("`icimethod'", "ex") != 1) & (strpos("`icimethod'", "wo") != 1) & (strpos("`icimethod'", "co") != 1) { di as error "Option `icimethod' not allowed in cimethod(`cimethod')" exit } } if ("`icimethod'" == "") & "`outplot'" == "or" { local icimethod "woolf" } //iRR if "`design'" == "mcbnetwork" & "`outplot'" == "rr" { local icimethod "CML" } if ("`design'" == "pcbnetwork" | "`design'" == "comparative") & "`outplot'" == "rr" { local icimethod "Koopman" } //Summary if "`ocimethod'" != "" { if (strpos("`ocimethod'", "t") != 1) & (strpos("`ocimethod'", "w") != 1){ di as error "Option `ocimethod' not allowed in cimethod(`cimethod')" exit } } else { local ocimethod "wald" } } if "`outplot'" == "abs" { if "`cimethod'" != "" { tokenize "`cimethod'", parse(",") local icimethod "`1'" if "`3'" != "" { local ocimethod = strltrim("`3'") } } if "`icimethod'" != "" { if (strpos("`icimethod'", "ex") != 1) & (strpos("`icimethod'", "wi") != 1) & (strpos("`icimethod'", "wa") != 1) & (strpos("`icimethod'", "e") != 1) & (strpos("`icimethod'", "ag") != 1) & (strpos("`icimethod'", "je") != 1) { di as error "Option `icimethod' not allowed in cimethod(`cimethod')" exit } } else { local icimethod "wilson" } if "`ocimethod'" != "" { if "`model'" == "random" | "`model'" == "fixed" { if (strpos("`ocimethod'", "t") != 1) & (strpos("`ocimethod'", "w") != 1){ di as error "Option `ocimethod' not allowed in cimethod(`cimethod')" exit } } else { if (strpos("`ocimethod'", "ex") != 1) & (strpos("`ocimethod'", "wi") != 1) & (strpos("`ocimethod'", "wa") != 1) & (strpos("`icimethod'", "e") != 1) & (strpos("`ocimethod'", "ag") != 1) & (strpos("`ocimethod'", "je") != 1) { di as error "Option `ocimethod' not allowed in cimethod(`cimethod')" exit } } } else { if "`model'" == "random" | "`model'" == "fixed" { local ocimethod "wald" } else { local ocimethod "wilson" } } } if "`prediction'" != "" & "`outplot'" != "abs" { local prediction di as res "NOTE: Predictions only computed for absolute measures. The option _prediction_ will be ignored" } //check no underscore in the variable names if strpos("`regressors'", "_") != 0 { di as error "Underscore is a reserved character and covariate(s) containing underscore(s) is(are) not allowed" di as error "Rename the covariate(s) to remove the underscore(s) character(s)" exit } if `p' < 2 & "`interaction'" !="" & ("`design'" != "`mcbnetwork'" | "`design'" != "`pcbnetwork'" ) { di as error "Interactions allowed with atleast 2 covariates" exit } //======================================================================================================================= tempfile master qui save "`master'" *declare study labels for display if "`label'"!="" { tokenize "`label'", parse("=,") while "`1'"!="" { cap confirm var `3' if _rc!=0 { di as err "Variable `3' not defined" exit } local `1' "`3'" mac shift 4 } } qui { *put name/year variables into appropriate macros if "`namevar'"!="" { local lbnvl : value label `namevar' if "`lbnvl'"!="" { quietly decode `namevar', gen(`neolabel') } else { gen str10 `neolabel'="" cap confirm string variable `namevar' if _rc==0 { replace `neolabel'=`namevar' } else if _rc==7 { replace `neolabel'=string(`namevar') } } } if "`namevar'"=="" { cap confirm numeric variable `studyid' if _rc != 0 { gen `neolabel' = `studyid' } if _rc == 0{ gen `neolabel' = string(`studyid') } } if "`yearvar'"!="" { local yearvar "`yearvar'" cap confirm string variable `yearvar' if _rc==7 { local str "string" } if "`namevar'"=="" { replace `neolabel'=`str'(`yearvar') } else { replace `neolabel'=`neolabel'+" ("+`str'(`yearvar')+")" } } } if "`design'" == "mcbnetwork" | "`design'" =="pcbnetwork" { longsetup `varlist', rid(`rid') assignment(`assignment') event(`event') total(`total') idpair(`idpair') `design' qui gen `ipair' = "Yes" qui replace `ipair' = "No" if `idpair' } else { qui gen `rid' = _n } //byvar if "`by'" != "" { cap confirm string variable `by' if _rc != 0 { di as error "The by() variable should be a string" exit _rc } if strpos(`"`varlist'"', "`by'") == 0 { tempvar byvar my_ncod `byvar', oldvar(`by') drop `by' rename `byvar' `by' } } buildregexpr `varlist', `interaction' `alphasort' `design' ipair(`ipair') `baselevel' studyid(`studyid') local regexpression = r(regexpression) local catreg = r(catreg) local contreg = r(contreg) local basecode = r(basecode) if "`interaction'" != "" { local varx = r(varx) local typevarx = r(typevarx) } if "`design'" == "comparative" { *local varx : word 1 of `regressors' gettoken varx catreg : catreg local typevarx = "i" local baselab:label `varx' 1 } if "`design'" == "pcbnetwork" | "`design'" == "mcbnetwork" { local varx = "`ipair'" local typevarx = "i" } local pcont: word count `contreg' if "`typevarx'" != "" & "`typevarx'" == "c" { local ++pcont } if `pcont' > 0 { local continuous = "continuous" } /*Model presenations*/ if ("`design'" == "general" | "`design'" == "comparative" ) { local nu = "mu" } else if "`design'" == "pcbnetwork" | "`design'" == "mcbnetwork" { if "`interaction'" != "" { local nu = "Ipair*`Comparator' + `Index'" } else { local nu = "mu + Ipair + `Index'" } } else if "`design'" == "abnetwork" { local nu = "mu.`first'" } local VarX: word 1 of `regressors' forvalues i=1/`p' { local c:word `i' of `regressors' local nu = "`nu' + `c'" if "`interaction'" != "" & `i' > 1 { local nu = "`nu' + `c'*`VarX'" } } if ("`catreg'" != " " | "`typevarx'" =="i" | ("`design'" == "comparative" | "`design'" == "mcbnetwork" | "`design'" == "pcbnetwork")) { if "`design'" == "mcbnetwork" | "`design'" == "pcbnetwork" { local catregs = "`catreg' `Index'" } if "`design'" == "comparative" { local catregs = "`catreg' `varx'" } if "`design'" == "abnetwork" { tokenize `catreg' macro shift local catregs "`*'" } if "`design'" == "general" { local catregs "`catreg'" } } if "`subgroup'" == "" & ("`catreg'" != "" | "`typevarx'" =="i" ) { if "`outplot'" == "abs" { if "`typevarx'" =="i" { local groupvar = "`varx'" } else { local groupvar : word 1 of `catreg' } } if "`outplot'" != "abs" & "`varx'" != "" { local groupvar : word 1 of `catreg' } } if "`by'" != "" { local groupvar "`by'" local byvar "`by'" *How many times to loop qui label list `by' local nlevels = r(max) } if "`design'" == "abnetwork" { local groupvar "`first'" local overall "nooverall" if "`outplot'" != "abs" { local itable "noitable" } } *Stratify not allow in pcbnetwork, mcbnetwork or abnetwork analysis if "`stratify'" != "" { if ("`design'" == "pcbnetwork") | ("`design'" == "mcbnetwork") | ("`design'" == "abnetwork") { di as res "NOTE: The option stratify is ignored in `design' analysis" local stratify } } *Check by is active & that there are more than 1 levels if "`stratify'" != "" { if "`by'" == "" { di as error "The by() variable needs to be specified in stratified analysis" exit } else { if `nlevels' < 2 { di as error "The by() variable should have atleast 2 categories in stratified analysis" exit } } } //nullify groupvar if its the studyid if "`groupvar'" == "`studyid'" { local groupvar } if "`groupvar'" == "" { local subgroup nosubgroup } qui gen `use' = . *Loop should begin here if "`stratify'" == "" { local nlevels = 0 } local i = 1 local byrownames local bybirownames if "`design'" == "abnetwork" { local hetdim 7 } else { if (`p' == 0) & ("`model'" == "random") & ("`design'" != "pcbnetwork" | "`design'" != "mcbnetwork" ) { local hetdim 5 } else { local hetdim 4 } } //Should run atleast once while `i' < `=`nlevels' + 2' { local modeli = "`model'" local modeloptsi = "`modelopts'" //don't run last loop if stratify if (`i' > `nlevels') & ("`stratify'" != "") & ("`design'" == "comparative") { continue, break } *Stratify except the last loop for the overall if (`i' < `=`nlevels' + 1') & ("`stratify'" != "") { local strataif `"if `by' == `i'"' local ilab:label `by' `i' local stratalab `":`by' = `ilab'"' local ilab = ustrregexra("`ilab'", " ", "_") local byrownames = "`byrownames' `by':`ilab'" if "`design'" == "comparative" & "`stratify'" != "" { local bybirownames = "`bybirownames' `ilab':`baselab' `ilab':`ilab'" } *Check if there is enough data in each strata //Number of obs in the analysis qui egen `obsid' = group(`rid') if `by' == `i' qui summ `obsid' local Nobs= r(max) drop `obsid' //Number of studies in the analysis qui egen `uniq' = group(`studyid') if `by' == `i' qui summ `uniq' local Nuniq = r(max) drop `uniq' } else { //Nullify local strataif local stratalab ": Full" if "`stratify'" != "" { local byrownames = "`byrownames' Overall" } //Number of obs in the analysis qui count local Nobs= r(N) if "`design'" == "mcbnetwork" | "`design'" == "pcbnetwork" { local Nobs = `Nobs'*0.5 } qui egen `uniq' = group(`studyid') qui summ `uniq' local Nuniq = r(max) drop `uniq' } if "`design'" == "comparative" { cap assert mod(`Nobs', 2) == 0 if _rc != 0 { di as error "Comparative analysis requires 2 observations per study" exit _rc } } if "`design'" == "abnetwork" { cap assert `Nobs'/`Nuniq' >= 2 if _rc != 0 { di as error "abnetwork design requires atleast 2 observations per study" exit _rc } } if (`Nobs' < 3 & "`modeli'" != "hexact" & "`design'" != "comparative") | ((`Nobs' < 5 ) & ("`modeli'" == "random") & ("`design'" == "comparative")) { local modeli hexact //If less than 3 studies, use exact model if "`modeloptsi'" != "" { local modeloptsi noi di as res _n "Warning: `model'-effects model options ignored." noi di as res _n "Warning: Homo-exact model fitted instead." } } di as res _n "*********************************** Fitted model`stratalab' ***************************************" _n tokenize `depvars' if "`design'" == "general" | "`design'" == "abnetwork" | "`design'" == "comparative" { if "`link'" == "loglog" { di "{phang} (`2' - `1') ~ binomial(p, `2'){p_end}" } else{ di "{phang} `1' ~ binomial(p, `2'){p_end}" } } else if "`design'" == "mcbnetwork" { di "{phang} `1' + `2' ~ binomial(p, `1' + `2' + `3' + `4'){p_end}" di "{phang} `1' + `3' ~ binomial(p, `1' + `2' + `3' + `4'){p_end}" } else if "`design'" == "pcbnetwork" { di "{phang} `1' ~ binomial(p, `3'){p_end}" di "{phang} `2' ~ binomial(p, `3'){p_end}" } if "`modeli'" == "random" { if "`cov'" == "" { di "{phang} `link'(p) = `nu' + `studyid'{p_end}" } else { di "{phang} `link'(p) = `nu' + `first'.`studyid' + `studyid'{p_end}" } if "`cov'" == "" { di "{phang}`studyid' ~ N(0, tau2){p_end}" } if "`cov'" == "independent" { di "{phang}`studyid' ~ N(0, tau2){p_end}" di "{phang}`first'.`studyid' ~ N(0, sigma2){p_end}" } if "`cov'" == "unstructured" { di "{phang}`studyid',`first'.`studyid' ~ biv.normal(0, Sigma){p_end}" } } else if "`modeli'" == "fixed" { di "{phang} `link'(p) = `nu'{p_end}" } if "`design'" == "pcbnetwork" | "`design'" == "mcbnetwork" { di "{phang} Ipair = 0 if 1st pair{p_end}" di "{phang} Ipair = 1 if 2nd pair{p_end}" } if "`design'" == "abnetwork" { di "{phang}`first' ~ N(0, sigma2){p_end}" qui label list `first' local nfirst = r(max) } if ("`catreg'" != " " | "`typevarx'" =="i" | ("`design'" == "comparative" | "`design'" == "mcbnetwork" | "`design'" == "pcbnetwork")) { di _n "{phang}Base levels{p_end}" di _n as txt "{pmore} Variable -- Base Level{p_end}" } foreach fv of local catregs { local lab:label `fv' 1 if "`fv'" != "`studyid'" { di "{pmore} `fv' -- `lab'{p_end}" } } if "`design'" == "abnetwork" { local lab:label `first' `basecode' di "{pmore} `first' -- `lab'{p_end}" } di _n di "{phang}" as txt "Number of observations = " as res "`Nobs'{p_end}" di "{phang}" as txt "Number of studies = " as res "`Nuniq'{p_end}" if "`design'" == "abnetwork" { di "{phang}" as txt "Number of `first's = " as res "`nfirst'{p_end}" } di _n"*********************************** ************* ***************************************" _n *Run model if more than 1 study if (`Nobs' > 1) { preg `event' `total' `strataif', rid(`rid') studyid(`studyid') use(`use') regexpression(`regexpression') nu(`nu') /// regressors(`regressors') catreg(`catreg') contreg(`contreg') level(`level') varx(`varx') typevarx(`typevarx') /// `progress' model(`modeli') modelopts(`modeloptsi') `mc' `interaction' `design' by(`by') `stratify' baselevel(`basecode') /// comparator(`Comparator') cimethod(`ocimethod') `gof' nsims(`nsims') link(`link') /// modeles(`modeles') modellci(`modellci') modeluci(`modeluci') outplot(`outplot') `smooth' cov(`cov') mat `logoddsi' = r(logodds) mat `popabsouti' = r(popabsout) local mdf = r(mdf) //mdf = 0 if saturated if "`catreg'" != " " | "`typevarx'" == "i" { mat `rrouti' = r(rrout) mat `poprrouti' = r(poprrout) mat `orouti' = r(orout) mat `poporouti' = r(poporout) mat `poplorouti' = r(poplorout) local inltest = r(inltest) if "`inltest'" == "yes" & "`stratify'" == "" { mat `nltestRR' = r(nltestRR) mat `nltestOR' = r(nltestOR) } } else{ local rr "norr" } if (`p' > 0) & ("`mc'" =="") { mat `mctest' = r(mctest) } mat `absouti' = r(absout) mat `absoutpi' = r(absoutp) if "`modeli'" == "random" { mat `hetouti' = r(hetout) } else { /*if "`design'" != "comparative" { mat `absoutpi' = J(1, 2, 0) } else { mat `absoutpi' = J(2, 2, 0) }*/ mat `hetouti' = J(1, `hetdim', .) } } *if 1 study or exact inference else { mat `logoddsi' = J(1, 6, .) mat `popabsouti' = J(1, 5, .) mat `absouti' = J(1, 6, .) mat `absoutpi' = J(1, 2, .) mat `hetouti' = J(1, `hetdim', .) mat `rrouti' = J(1, 6, 1) mat `poprrouti' = J(1, 5, 1) mat `orouti' = J(1, 6, 1) mat `poporouti' = J(1, 5, 1) mat `poplorouti' = J(1, 5, 1) qui replace `use' = 1 `strataif' } *Stack the matrices if `i' == 1 { mat `absout' = `absouti' if "`rr'" == "" { mat `rrout' = `rrouti' mat `poprrout' = `poprrouti' mat `orout' = `orouti' mat `poporout' = `poporouti' mat `poplorout' = `poplorouti' } mat `logodds' = `logoddsi' mat `popabsout' = `popabsouti' mat `absoutp' = `absoutpi' mat `hetout' = `hetouti' } else { mat `absout' = `absout' \ `absouti' mat `popabsout' = `popabsout' \ `popabsouti' if "`rr'" == "" { mat `rrout' = `rrout' \ `rrouti' mat `poprrout' = `poprrout' \ `poprrouti' mat `orout' = `orout' \ `orouti' mat `poporout' = `poporout' \ `poporouti' mat `poplorout' = `poplorout' \ `poplorouti' } mat `logodds' = `logodds' \ `logoddsi' mat `absoutp' = `absoutp' \ `absoutpi' mat `hetout' = `hetout' \ `hetouti' } local ++i } *End loop //rownames for the matrix if "`stratify'" != "" & `i' > 1 { mat rownames `hetout' = `byrownames' if "`design'" != "comparative" { mat rownames `absout' = `byrownames' mat rownames `popabsout' = `byrownames' mat rownames `absoutp' = `byrownames' mat rownames `logodds' = `byrownames' } else { mat rownames `absout' = `bybirownames' mat rownames `popabsout' = `bybirownames' mat rownames `absoutp' = `bybirownames' mat rownames `logodds' = `bybirownames' } if "`rr'" == "" { mat rownames `rrout' = `byrownames' mat rownames `poprrout' = `byrownames' mat rownames `orout' = `byrownames' mat rownames `poporout' = `byrownames' mat rownames `poplorout' = `byrownames' } } //If stratify, no overall for comparative if "`stratify'" != "" & "`design'" == "comparative" { local overall "nooverall" } //CI if "`outplot'" != "abs" { local se } if "`outplot'" != "abs" & "`design'" == "abnetwork" { local summaryonly "summaryonly" local smooth } if "`design'" == "mcbnetwork" | "`design'" == "pcbnetwork" { *widesetup `event' `total', sid(`rid') idpair(`assignment') jvar(`comparator') sort `rid' qui drop `assignment' `ipair' qui reshape wide `event' `total' _WT `modeles' `modellci' `modeluci', i(`rid') j(`idpair') //Add the weights qui gen _WT = _WT0 + _WT1 qui drop _WT0 _WT1 qui gen `modeles' = `modeles'1 qui drop `modeles'0 `modeles'1 qui gen `modellci' = `modellci'1 qui drop `modellci'0 `modellci'1 qui gen `modeluci' = `modeluci'1 qui drop `modeluci'0 `modeluci'1 } qui metapregci `depvars', studyid(`studyid') first(`first') es(`es') se(`se') uci(`uci') lci(`lci') `design' /// id(`id') rid(`rid') regressors(`regressors') outplot(`outplot') level(`level') /// cimethod(`icimethod') lcols(`lcols') rcols(`rcols') sortby(`sortby') by(`by') /// modeles(`modeles') modellci(`modellci') modeluci(`modeluci') `smooth' local depvars = r(depvars) local rcols = r(rcols) local lcols = r(lcols) local sortby = r(sortby) if (`p' > 0) { local indvars = r(regressors) } if `mdf' == 0 { local smooth } prep4show `id' `use' `neolabel' `es' `lci' `uci' `modeles' `modellci' `modeluci', `design' /// sortby(`sortby') groupvar(`groupvar') grptotal(`grptotal') se(`se') /// outplot(`outplot') rrout(`rrout') poprrout(`poprrout') orout(`orout') poporout(`poporout') /// absout(`absout') popabsout(`popabsout') absoutp(`absoutp') hetout(`hetout') /// `subgroup' `summaryonly' dp(`dp') pcont(`pcont') model(`model') `prediction' /// `overall' download(`download') indvars(`indvars') depvars(`depvars') `stratify' level(`level') if "`itable'" == "" { disptab `id' `use' `neolabel' `es' `lci' `uci' `grptotal' `modeles' `modellci' `modeluci', /// `itable' dp(`dp') power(`power') `design' `summaryonly' /// `subgroup' sumstat(`sumstat') level(`level') `wt' `smooth' /// ocimethod(`ocimethod') icimethod(`icimethod') model(`model') groupvar(`groupvar') outplot(`outplot') } //Extra tables if ("`sumtable'" != "none") { di as res _n "****************************************************************************************" } //logodds if (("`sumtable'" == "all") |(strpos("`sumtable'", "logit") != 0)) { printmat, matrixout(`logodds') type(logit) p(`p') dp(`dp') power(`power') `continuous' model(`model') } //abs if (("`sumtable'" == "all") |(strpos("`sumtable'", "abs") != 0)) { printmat, matrixout(`absout') type(abs) p(`p') dp(`dp') power(`power') `continuous' model(`model') } //Pop p if (("`sumtable'" == "all") |(strpos("`sumtable'", "abs") != 0)) & "`model'" !="hexact" { printmat, matrixout(`popabsout') type(popabs) dp(`dp') power(`power') nsims(`nsims') } //het if "`model'" =="random" { printmat, matrixout(`hetout') type(het) dp(`dp') `design' } //rr if (("`sumtable'" == "all") | (strpos("`sumtable'", "rr") != 0)) & (("`catreg'" != " ") | ("`typevarx'" == "i")) { //rr printmat, matrixout(`rrout') type(rr) p(`p') dp(`dp') power(`power') model(`model') //rr equal if "`inltest'" == "yes" { printmat, matrixout(`nltestRR') type(rre) dp(`dp') } printmat, matrixout(`poprrout') type(poprr) p(`p') dp(`dp') power(`power') model(`model') nsims(`nsims') } //or if (("`sumtable'" == "all") | (strpos("`sumtable'", "or") != 0)) & (("`catreg'" != " ") | ("`typevarx'" == "i")) { //rr printmat, matrixout(`orout') type(or) p(`p') dp(`dp') power(`power') model(`model') //or equal if "`inltest'" == "yes" { printmat, matrixout(`nltestOR') type(ore) dp(`dp') } printmat, matrixout(`poporout') type(popor) p(`p') dp(`dp') power(`power') model(`model') nsims(`nsims') } //model comparison if ((`p' > 0 & "`design'" != "abnetwork") | (`p' > 1 & "`design'" == "abnetwork")) & ("`mc'" =="") { printmat, matrixout(`mctest') type(mc) dp(`dp') } //Draw the forestplot if "`graph'" == "" { fplot `es' `lci' `uci' `use' `neolabel' `grptotal' `id' `modeles' `modellci' `modeluci', model(`model') /// studyid(`studyid') power(`power') dp(`dp') level(`level') /// groupvar(`groupvar') `prediction' /// outplot(`outplot') lcols(`lcols') rcols(`rcols') /// ciopts(`ciopts') astext(`astext') diamopts(`diamopts') /// olineopts(`olineopts') sumstat(`sumstat') pointopt(`pointopts') boxopt(`boxopts') /// `double' `subline' texts(`texts') `xlabel' `xtick' /// `ovline' `stats' graphsave(`graphsave')`fopts' `xline' `logscale' `design' `wt' `box' `smooth' } cap ereturn clear cap confirm matrix `mctest' if _rc == 0 { ereturn matrix mctest = `mctest' } cap confirm matrix `hetout' if _rc == 0 { ereturn matrix hetout = `hetout' } cap confirm matrix `nltestRR' if _rc == 0 { ereturn matrix rrtest = `nltestRR' ereturn matrix ortest = `nltestOR' } cap confirm matrix `logodds' if _rc == 0 { ereturn matrix logodds = `logodds' ereturn matrix popabsout = `popabsout' } cap confirm matrix `absout' if _rc == 0 { ereturn matrix absout = `absout' } cap confirm matrix `absoutp' if _rc == 0 { ereturn matrix absoutp = `absoutp' } cap confirm matrix `rrout' if _rc == 0 { ereturn matrix rrout = `rrout' ereturn matrix poprrout = `poprrout' ereturn matrix orout = `orout' ereturn matrix poporout = `poporout' ereturn matrix poplorout = `poplorout' } restore end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: ESTCOVAR +++++++++++++++++++++++++ Compose the var-cov matrix +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop estcovar program define estcovar, rclass version 14.1 syntax, matrix(name) cov(string) [predcmd(string)] *matrix is colvector tempname matcoef rosevar rawvar mat `matcoef' = `matrix'' local nrows = rowsof(`matcoef') *Initialize - Default mat `rosevar' = (0, 0\ /// 0, 0) mat `rawvar' = (0, 0\ /// 0, 0) if "`predcmd'" == "meqrlogit_p" { if strpos("`cov'", "uns") != 0 { mat `rosevar' = (exp(`matcoef'[`nrows' - 1 , 1])^2, exp(`matcoef'[ `nrows' - 1, 1])*exp(`matcoef'[`nrows' - 2, 1])*tanh(`matcoef'[ `nrows', 1])\ /// exp(`matcoef'[ `nrows' - 1, 1])*exp(`matcoef'[`nrows' - 2, 1])*tanh(`matcoef'[ `nrows', 1]), exp(`matcoef'[ `nrows' - 2, 1])^2) mat `rawvar' = (`matcoef'[`nrows' - 1 , 1], `matcoef'[ `nrows', 1]\ /// `matcoef'[ `nrows', 1], `matcoef'[ `nrows' - 2, 1]) local k = 3 } else if strpos("`cov'", "ind") != 0 { mat `rawvar' = (`matcoef'[ `nrows', 1], 0\ /// 0, `matcoef'[ `nrows' - 1, 1]) mat `rosevar' = (exp(`matcoef'[ `nrows', 1])^2, 0\ /// 0, exp(`matcoef'[ `nrows'-1, 1])^2) local k = 2 } } else { if strpos("`cov'", "uns") != 0 { mat `rosevar' = (`matcoef'[`nrows' - 1 , 1], `matcoef'[ `nrows', 1] \ /// `matcoef'[ `nrows', 1], `matcoef'[ `nrows' - 2, 1]) mat `rawvar' = (`matcoef'[`nrows' - 1 , 1], `matcoef'[ `nrows', 1] \ /// `matcoef'[ `nrows', 1], `matcoef'[ `nrows' - 2, 1]) local k = 3 } else if strpos("`cov'", "ind") != 0 { mat `rawvar' = (`matcoef'[ `nrows', 1], 0 \ /// 0, `matcoef'[ `nrows' - 1, 1]) mat `rosevar' = (`matcoef'[ `nrows', 1], 0 \ /// 0, `matcoef'[ `nrows'-1, 1]) local k = 2 } } return matrix rosevar = `rosevar' return matrix rawvar = `rawvar' return local k = `k' end /************************************************************************************************** METAPREGCI - CONFIDENCE INTERVALS **************************************************************************************************/ capture program drop metapregci program define metapregci, rclass version 14.1 #delimit ; syntax varlist(min=2 max=4), studyid(varname) [first(varname) es(name) se(name) uci(name) lci(name) id(name) rid(varname) regressors(varlist) outplot(string) level(integer 95) by(varname) cimethod(string) lcols(varlist) rcols(varlist) mcbnetwork pcbnetwork sortby(varlist) comparative abnetwork general modeles(varname) modellci(varname) modeluci(varname) smooth ]; #delimit cr tempvar uniq event event1 event2 total total1 total2 a b c d idpair *gettoken idpair confounders : regressors tokenize `varlist' if "`mcbnetwork'`pcbnetwork'" == "" { generate `event' = `1' generate `total' = `2' local depvars "`1' `2'" } else if "`mcbnetwork'" != "" { gen `a' = `1' gen `b' = `2' gen `c' = `3' gen `d' = `4' local depvars "`1' `2' `3' `4'" gen `id' = _n } else { generate `event1' = `1' generate `event2' = `2' generate `total1' = `3' generate `total2' = `3' local depvars "`1' `2' `3'" gen `id' = _n } if "`outplot'" != "abs" { if "`abnetwork'" != "" { gen `id' = _n gen `es' = . gen `lci' = . gen `uci' = . } if "`mcbnetwork'" != "" { if "`outplot'" == "rr" { //constrained maximum likelihood estimation cmlci `a' `b' `c' `d', r(`es') upperci(`uci') lowerci(`lci') alpha(`=1 - `level'*0.01') } if "`outplot'" == "or" { orccci `a' `b' `c' `d', r(`es') upperci(`uci') lowerci(`lci') level(`level') `mcbnetwork' cimethod(`cimethod') } } if "`pcbnetwork'" !="" { if "`outplot'" == "rr" { koopmanci `event1' `total1' `event2' `total2', r(`es') upperci(`uci') lowerci(`lci') alpha(`=1 - `level'*0.01') } if "`outplot'" == "or" { orccci `event1' `total1' `event2' `total2', r(`es') upperci(`uci') lowerci(`lci') level(`level') cimethod(`cimethod') *orccci `a' `b' `c' `d', r(`es') upperci(`uci') lowerci(`lci') level(`level') `pcbnetwork' cimethod(`cimethod') } } if "`comparative'" != "" { egen `id' = group(`studyid' `by') sort `id' `rid' by `id': egen `idpair' = seq() qui count local Nobs = r(N) /*Check if the number of studies is half*/ cap assert mod(`Nobs', 2) == 0 if _rc != 0 { di as error "More than two observations per study for some studies" exit _rc, STATA } sort `id' `idpair' if "`=`studyid'[1]'" != "`=`studyid'[2]'" { di as error "Data not properly sorted. `studyid' in row 1 and 2 should be the same. " exit _rc, STATA } widesetup `event' `total' `confounders' , sid(`id') idpair(`idpair') sortby(`sortby') local vlist = r(vlist) local cc0 = r(cc0) local cc1 = r(cc1) if "`outplot'" == "rr" { koopmanci `event'1 `total'1 `event'0 `total'0, r(`es') upperci(`uci') lowerci(`lci') alpha(`=1 - `level'*0.01') } if "`outplot'" == "or" { orccci `event'1 `total'1 `event'0 `total'0, r(`es') upperci(`uci') lowerci(`lci') level(`level') cimethod(`cimethod') } //Rename the varying columns local newcc0: label `first' `cc0' local newcc1: label `first' `cc1' foreach v of local vlist { rename `v'0 `v'_`cc0' label var `v'_`cc0' "`v'_`newcc0'" rename `v'1 `v'_`cc1' label var `v'_`cc1' "`v'_`newcc1'" } //Add the weights qui gen _WT = _WT_1 + _WT_2 qui drop _WT_1 _WT_2 //Remove unnecessary columns if "`smooth'" !="" { qui drop `modeles'_1 rename `modeles'_2 `modeles' qui drop `modellci'_1 rename `modellci'_2 `modellci' qui drop `modeluci'_1 rename `modeluci'_2 `modeluci' } //make new lcols foreach lcol of local lcols { local lenvar = strlen("`lcol'") foreach v of local vlist { local matchstr = substr("`v'", 1, `lenvar') if strmatch("`matchstr'", "`lcol'") == 1 { continue, break } } if strmatch("`matchstr'", "`lcol'") == 1 { local lcols_r "`lcols_r' `lcol'_`cc0' `lcol'_`cc1'" } else { local lcols_r "`lcols_r' `lcol'" } } local lcols "`lcols_r'" //make new rcols foreach rcol of local rcols { local lenvar = strlen("`rcol'") foreach v of local vlist { local matchstr = substr("`v'", 1, `lenvar') if strmatch("`matchstr'", "`rcol'") == 1 { continue, break } } if strmatch("`matchstr'", "`rcol'") == 1 { local rcols_r "`rcols_r' `rcol'_`cc0' `rcol'_`cc1'" } else { local rcols_r "`rcols_r' `rcol'" } } local rcols "`rcols_r'" //make new sortby foreach byv of local sortby { local lenvar = strlen("`byv'") foreach v of local vlist { local matchstr = substr("`v'", 1, `lenvar') if strmatch("`matchstr'", "`byv'") == 1 { continue, break } } if strmatch("`matchstr'", "`byv'") == 1 { local rcols_r "`sortby_r' `byv'_`cc0' `byv'_`cc1'" } else { local sortby_r "`sortby_r' `byv'" } } local sortyby "`sortby_r'" //make new depvars foreach depvar of local depvars { local lenvar = strlen("`depvar'") foreach v of local vlist { local matchstr = substr("`v'", 1, `lenvar') if strmatch("`matchstr'", "`depvar'") == 1 { continue, break } } if strmatch("`matchstr'", "`depvar'") == 1 { local depvars_r "`depvars_r' `depvar'_`cc0' `depvar'_`cc1'" } else { local depvars_r "`depvars_r' `depvar'" } } local depvars "`depvars_r'" //make new indvars foreach indvar of local confounders { local lenvar = strlen("`indvar'") foreach v of local vlist { local matchstr = substr("`v'", 1, `lenvar') if strmatch("`matchstr'", "`indvar'") == 1 { continue, break } } if strmatch("`matchstr'", "`indvar'") == 1 { local indvars_r "`indvars_r' `indvar'_`cc0' `indvar'_`cc1'" } else { local indvars_r "`indvars_r' `indvar'" } } local regressors "`indvars_r'" local p: word count `confounders' if `p' == 0 { local regressors = " " } } } else { metapreg_propci `total' `event', p(`es') se(`se') lowerci(`lci') upperci(`uci') cimethod(`cimethod') level(`level') gen `id' = _n } if "`rcols'" =="" { local rcols = " " } if "`lcols'" =="" { local lcols = " " } if "`sortby'" == "" { local sortby = " " } return local regressors = "`regressors'" return local depvars = "`depvars'" return local rcols = "`rcols'" return local lcols = "`lcols'" return local sortby = "`sortby'" end /************************************************************************************************** PREG - REGRESSIONS **************************************************************************************************/ capture program drop preg program define preg, rclass version 14.1 #delimit ; syntax varlist(min=2) [if] [in], studyid(varname) use(varname) [ regexpression(string) nu(string) baselevel(passthru) rid(varname) regressors(varlist) varx(varname) typevarx(string) comparator(varname) catreg(varlist) contreg(varlist) cimethod(string) cov(string) level(integer 95) DP(integer 2) progress model(string) modelopts(string) outplot(string) noMC noCONstant interaction comparative mcbnetwork pcbnetwork abnetwork by(varname) stratify GOF nsims(string) link(string) modeles(varname) modelse(varname) modellci(varname) modeluci(varname) smooth *]; #delimit cr marksample touse, strok tempvar event nonevent total invtotal predevent ill iw tempname coefmat coefvar testlr V logodds absout absoutp rrout orout nltestRR nltestOR /// hetout mctest absexact newobs matgof popabsout poprrout poporout poplorout rosevar rawvar tokenize `varlist' qui { gen `event' = `1' gen `total' = `2' gen `nonevent' = `total' - `event' } //fit the model if "`progress'" != "" { local echo noi } else { local echo qui } //Just initialize gettoken first confounders : regressors local p: word count `regressors' if "`mcbnetwork'`pcbnetwork'" != "" { tokenize `regexpression' local one "`1'" local two "`2'" local three "`3'" if "`interaction'" != "" { tokenize `one', parse("#") tokenize `1', parse(".") local ipair "`3'" tokenize `two', parse(".") local index "`3'" } else { tokenize `two', parse(".") local ipair "`3'" tokenize `three', parse(".") local index "`3'" } } //Which outcome to model if "`link'" == "loglog" { local outcome "`nonevent'" } else { local outcome "`event'" } `echo' fitmodel `outcome' `total' if `touse', modelopts(`modelopts') model(`model') regexpression(`regexpression') /// sid(`studyid') level(`level') nested(`first') `abnetwork' cov(`cov') link(`link') estimates store metapreg_modest local predcmd = e(predict) qui replace _ESAMPLE = e(sample) qui replace `use' = 1 if (_ESAMPLE == 1) mat `coefmat' = e(b) mat `coefvar' = e(V) local DF = e(N) - e(k) local mdf = e(df) //mdf = 0 if saturated model if "`model'" == "random" { local BHET = e(chi2_c) local P_BHET = e(p_c) if "`abnetwork'" == "" { local DF_BHET = 1 } else { local DF_BHET = 2 } if "`cov'" != "" { estcovar, matrix(`coefmat') cov(`cov') predcmd(`predcmd') local DF_BHET = r(k) mat `rosevar' = r(rosevar) //var-cov matrix mat `rawvar' = r(rawvar) //raw var-cov matrix mat colnames `rosevar' = intercept slope mat rownames `rosevar' = intercept slope mat colnames `rawvar' = intercept slope mat rownames `rawvar' = intercept slope } } else { local BHET = . local P_BHET = . local DF_BHET = . } qui estat ic mat `matgof' = r(S) local BIC = `matgof'[1, 6] //Display GOF if ("`gof'" != "") { di as text "Goodness of Fit Criterion" mat `matgof' = `matgof'[1..., 5..6] mat rownames `matgof' = Value #delimit ; noi matlist `matgof', cspec(& %7s | %8.`=`dp''f & %8.`=`dp''f o2&) rspec(&-&) underscore nodotz ; #delimit cr } if "`model'" == "hexact" { qui { //Exact inference mat `absexact' = J(1, 6, .) sum `event' if `touse' local sumevent = r(sum) sum `total' if `touse' local sumtotal = r(sum) local DF = r(N) - 1 cii prop `sumtotal' `sumevent', `cimethod' level(`level') mat `absexact'[1, 1] = r(proportion) mat `absexact'[1, 2] = r(se) mat `absexact'[1, 5] = r(lb) mat `absexact'[1, 6] = r(ub) local zvalue = (`absexact'[1, 1] - 0.5)/sqrt(0.25/`sumtotal') mat `absexact'[1, 3] = `zvalue' local pvalue = normprob(-abs(`zvalue'))*2 mat `absexact'[1, 4] = `pvalue' } } //Obtain the prediction if "`model'" != "hexact" { //if random, needs atleast 7 studies to run predict command qui count local nobs = r(N) if "`model'" == "random" { if ((`nobs' < 7) & ("`model'" == "random")) { local multipler = int(ceil(7/`nobs')) qui expand `multipler', gen(`newobs') } } qui predict `predevent', mu //Revert to original data if filler data was generated if (("`model'" == "random") & (`nobs' < 7)) { qui keep if !`newobs' } } else { qui gen `predevent' = `absexact'[1, 1]*`total' if (_ESAMPLE == 1) } //compute the weight if "`model'" == "random" { qui gen `iw' = `total'*(`predevent'/`total')*(1 - `predevent'/`total') } else { qui gen `iw' = `total' } //compute the relative weight *qui gen `ill' = `event'*ln(`predevent'/`total') + (`total' - `event')*ln(1 - (`predevent'/`total')) if (_ESAMPLE == 1) qui sum `iw' if (_ESAMPLE == 1) local W = r(sum) //compute the weights qui replace _WT = (`iw'/`W')*100 if (_ESAMPLE == 1) & (_WT == .) if "`model'" == "random" { local npar = colsof(`coefmat') if "`predcmd'" == "meqrlogit_p" { local scalefn "exp" local scalepow "2" } else { local scalepow "1" } if "`abnetwork'`cov'" == "" { local TAU21 = `scalefn'(`coefmat'[1, `npar'])^`scalepow' //Between study variance 1 local TAU22 = 0 } else if "`abnetwork'" != "" { local TAU21 = `scalefn'(`coefmat'[1, `=`npar'-1'])^`scalepow' //Between study variance 1 local TAU22 = `scalefn'(`coefmat'[1, `npar'])^`scalepow' //Between study variance 2 } else if "`cov'" != "" { local TAU21 = `rosevar'[1, 1] local TAU22 = `rosevar'[2, 2] if "`cov'" == "unstructured" { local rho = tanh(`rawvar'[1, 2]) } } } else { local TAU21 = 0 local TAU22 = 0 } local ISQ1 = . local ISQ2 = . if (`p' == 0) & ("`model'" == "random") & ("`pcbnetwork'`mcbnetwork'" == "") { /*Compute I2*/ qui gen `invtotal' = 1/`total' qui summ `invtotal' if `touse' local invtotal= r(sum) local K = r(N) local Esigma = (exp(`TAU21'*0.5 + `coefmat'[1, 1]) + exp(`TAU21'*0.5 - `coefmat'[1, 1]) + 2)*(1/(`K'))*`invtotal' local ISQ1 = `TAU21'/(`Esigma' + `TAU21')*100 } else if "`abnetwork'`cov'" != "" & ("`model'" == "random") { local ISQ1 = `TAU21'/(`TAU21' + `TAU22')*100 local ISQ2 = `TAU22'/(`TAU21' + `TAU22')*100 } local redindex 0 if ((`p' > 0 & "`abnetwork'" == "") | (`p' > 1 & "`abnetwork'" != "") | ("`interaction'" != "" & "`pcbnetwork'`mcbnetwork'" != "") ) & "`mc'" == "" { di _n"*********************************** ************* ***************************************" _n di as txt _n "Just a moment - Fitting reduced model(s) for comparison" if "`abnetwork'`interaction'" !="" { if "`mcbnetwork'`pcbnetwork'" != "" { local confariates "`comparator'" } else { local confariates "`confounders'" } } else { local confariates "`regressors'" } local initial 1 foreach c of local confariates { local nureduced if ("`interaction'" != "" & "`pcbnetwork'`mcbnetwork'" != "") { local omterm = "`c'*`ipair'" gettoken start end : regexpression local nureduced "mu i.`ipair' `end'" local eqreduced = "Ipair + `end'" } else { foreach term of local regexpression { if "`interaction'" != "" { if strpos("`term'", "`c'#") != 0 & strpos("`term'", "`first'") != 0 { local omterm = "`c'*`first'" } else { local nureduced "`nureduced' `term'" } } else{ if ("`term'" == "i.`c'")|("`term'" == "c.`c'")|("`term'" == "`c'") { local omterm = "`c'" } else { local nureduced "`nureduced' `term'" } } } local eqreduced = subinstr("`nu'", "+ `omterm'", "", 1) } local ++redindex di as res _n "`redindex'. Ommitted `omterm' in `link'(p)" if "`model'" == "random" { di as res "{phang} `link'(p) = `eqreduced' + `studyid'{p_end}" } else { di as res "{phang} `link'(p) = `eqreduced'{p_end}" } if "`omterm'" == "`first'" { local newcov } else { local newcov "`cov'" } `echo' fitmodel `outcome' `total' if `touse', modelopts(`modelopts') model(`model') /// regexpression(`nureduced') sid(`studyid') level(`level') nested(`first') `abnetwork' cov(`newcov') link(`link') qui estat ic mat `matgof' = r(S) local BICmc = `matgof'[1, 6] estimates store metapreg_Null //LR test the model qui lrtest metapreg_modest metapreg_Null, force local lrp :di %10.`dp'f chi2tail(r(df), r(chi2)) local lrchi2 = r(chi2) local lrdf = r(df) estimates drop metapreg_Null if `initial' == 1 { mat `mctest' = [`lrchi2', `lrdf', `lrp', `=`BIC' -`BICmc''] } else { mat `mctest' = `mctest' \ [`lrchi2', `lrdf', `lrp', `=`BIC' -`BICmc''] } local rownameslr "`rownameslr' `omterm'" local initial 0 } //Ultimate null model if (`p' > 1 & "`abnetwork'" == "") | (`p' > 2 & "`abnetwork'" != "") { local ++redindex di as res _n "`redindex'. Ommitted all covariate effects in `link'(p)" if "`abnetwork'" != "" { local regexpression "ibn.`first'" } else if "`pcbnetwork'`mcbnetwork'" != "" { local regexpression "mu i.`ipair' i.`index'" } else { local regexpression "mu" } `echo' fitmodel `outcome' `total' if `touse', modelopts(`modelopts') model(`model') regexpression(mu) /// sid(`studyid') level(`level') nested(`first') `abnetwork' link(`link') qui estat ic mat `matgof' = r(S) local BICmc = `matgof'[1, 6] estimates store metapreg_Null qui lrtest metapreg_modest metapreg_Null local lrchi2 = r(chi2) local lrdf = r(df) local lrp :di %10.`dp'f r(p) estimates drop metapreg_Null mat `mctest' = `mctest' \ [`lrchi2', `lrdf', `lrp', `=`BIC' -`BICmc''] local rownameslr "`rownameslr' All" } mat rownames `mctest' = `rownameslr' mat colnames `mctest' = chi2 df p Delta_BIC } //LOG ODDS estp, studyid(`studyid') estimates(metapreg_modest) `interaction' catreg(`catreg') contreg(`contreg') level(`level') model(`model') cimethod(`cimethod') /// varx(`varx') typevarx(`typevarx') by(`by') regexpression(`regexpression') `mcbnetwork' `comparative' `pcbnetwork' `abnetwork' `stratify' /// comparator(`comparator') link(`link') mat `logodds' = r(outmatrix) //simulations postsim, orderid(`rid') studyid(`studyid') todo(p) estimates(metapreg_modest) logodds(`logodds') /// level(`level') model(`model') by(`by') `comparative' `interaction' `abnetwork' /// `mcbnetwork' varx(`varx') cov(`cov') nsims(`nsims') link(`link') mat `popabsout' = r(outmatrix) //ABS estp, studyid(`studyid') estimates(metapreg_modest) `interaction' catreg(`catreg') /// contreg(`contreg') level(`level') model(`model') cimethod(`cimethod') /// varx(`varx') typevarx(`typevarx') expit by(`by') regexpression(`regexpression') /// `comparative' `mcbnetwork' `pcbnetwork' `abnetwork' `stratify' /// comparator(`comparator') link(`link') mat `absout' = r(outmatrix) mat `absoutp' = r(outmatrixp) //R if "`catreg'" != "" | "`typevarx'" == "i" { estr, studyid(`studyid') estimates(metapreg_modest) catreg(`catreg') /// level(`level') comparator(`comparator') `interaction' cimethod(`cimethod') /// varx(`varx') typevarx(`typevarx') by(`by') `mcbnetwork' `pcbnetwork' /// `comparative' `abnetwork' `stratify' /// regexpression(`regexpression') `baselevel' link(`link') mat `rrout' = r(rroutmatrix) mat `orout' = r(oroutmatrix) local inltest = r(inltest) if "`inltest'" == "yes" { mat `nltestRR' = r(nltestRR) //if RR by groups are equal mat `nltestOR' = r(nltestOR) //if RR by groups are equal } //simulations postsim, orderid(`rid') studyid(`studyid') todo(r) estimates(metapreg_modest) rrout(`rrout') orout(`orout') /// level(`level') model(`model') by(`by') `comparative' `interaction' `abnetwork' /// `baselevel' `mcbnetwork' varx(`varx') cov(`cov') nsims(`nsims') link(`link') mat `poprrout' = r(rroutmatrix) mat `poporout' = r(oroutmatrix) mat `poplorout' = r(loroutmatrix) } //Smooth estimates //simulations if "`smooth'" != "" { postsim, orderid(`rid') studyid(`studyid') todo(smooth) estimates(metapreg_modest) /// level(`level') model(`model') by(`by') `comparative' /// modeles(`modeles') modellci(`modellci') modeluci(`modeluci') outplot(`outplot') /// `interaction' `abnetwork' `mcbnetwork' varx(`varx') cov(`cov') nsims(`nsims') link(`link') } if "`model'" == "hexact" { cap confirm matrix `absout' if _rc == 0 { local nrowsp = rowsof(`absout') } else{ mat `absout' = `absexact' } //Replace the value with the exact forvalues r = 1(1)`nrowsp' { forvalues c = 1(1)6 { mat `absout'[`r', `c'] = `absexact'[1, `c'] } } mat colnames `absout' = Mean SE z(score) P>|z| Lower Upper } //=================================================================================== //Return the matrices if "`abnetwork'`cov'" != "" { if "`cov'" == "unstructured" { mat `hetout' = (`DF_BHET', `BHET' ,`P_BHET', `TAU21', `TAU22', `rho', `ISQ1', `ISQ2') mat colnames `hetout' = DF Chisq p tau2 sigma2 rho I2tau I2sigma } else { mat `hetout' = (`DF_BHET', `BHET' ,`P_BHET', `TAU21', `TAU22', `ISQ1', `ISQ2') mat colnames `hetout' = DF Chisq p tau2 sigma2 I2tau I2sigma } } else { if (`p' == 0) & ("`model'" == "random") & "`pcbnetwork'`mcbnetwork'" == "" { mat `hetout' = (`DF_BHET', `BHET' ,`P_BHET', `TAU21', `ISQ1') mat colnames `hetout' = DF Chisq p tau2 I2tau } else { mat `hetout' = (`DF_BHET', `BHET' ,`P_BHET', `TAU21') mat colnames `hetout' = DF Chisq p tau2 } } mat rownames `hetout' = Model return matrix hetout = `hetout' return local inltest = "`inltest'" cap confirm matrix `logodds' if _rc == 0 { return matrix logodds = `logodds' return matrix popabsout = `popabsout' } cap confirm matrix `absout' if _rc == 0 { return matrix absout = `absout' } cap confirm matrix `absoutp' if _rc == 0 { return matrix absoutp = `absoutp' } cap confirm matrix `rrout' if _rc == 0 { return matrix rrout = `rrout' return matrix poprrout = `poprrout' } cap confirm matrix `orout' if _rc == 0 { return matrix orout = `orout' return matrix poporout = `poporout' return matrix poplorout = `poplorout' } if "`inltest'" == "yes" { return matrix nltestRR = `nltestRR' return matrix nltestOR = `nltestOR' } cap confirm matrix `mctest' if _rc == 0 { return matrix mctest = `mctest' } return scalar mdf = `mdf' end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: myncod +++++++++++++++++++++++++ Decode by order of data +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop my_ncod program define my_ncod version 14.1 syntax newvarname(gen), oldvar(varname) qui { cap confirm numeric var `oldvar' tempvar by_num if _rc == 0 { decode `oldvar', gen(`by_num') drop `oldvar' rename `by_num' `oldvar' } * The _by variable is generated according to the original * sort order of the data, and not done alpha-numerically qui count local N = r(N) cap drop `varlist' gen `varlist' = 1 in 1 local lab = `oldvar'[1] cap label drop `oldvar' if "`lab'" != ""{ label define `oldvar' 1 "`lab'" } local found1 "`lab'" local max = 1 forvalues i = 2/`N'{ local thisval = `oldvar'[`i'] local already = 0 forvalues j = 1/`max'{ if "`thisval'" == "`found`j''"{ local already = `j' } } if `already' > 0{ replace `varlist' = `already' in `i' } else{ local max = `max' + 1 replace `varlist' = `max' in `i' local lab = `oldvar'[`i'] if "`lab'" != ""{ label define `oldvar' `max' "`lab'", modify } local found`max' "`lab'" } } label values `varlist' `oldvar' label copy `oldvar' `varlist', replace } end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: FITMODEL +++++++++++++++++++++++++ Fit the regression model +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop fitmodel program define fitmodel version 14.1 syntax varlist [if] [in], [ model(string) modelopts(string asis) regexpression(string) sid(varname) /// level(integer 95) mcbnetwork pcbnetwork abnetwork general comparative nested(string) cov(string) link(string)] marksample touse, strok tokenize `varlist' if "`cov'" != "" { local varx "`nested'" if "`cov'" == "unstructured" { local cov "cov(`cov')" } else { local cov } } else { local varx local cov } if "`abnetwork'" != "" & "`model'" == "random" { local nested = `"|| (`nested': )"' } else { local nested } //Specify the engine if "`link'" == "logit" { if _caller() >= 16 { local fitcommand "melogit" } else { local fitcommand "meqrlogit" } } else { local fitcommand "mecloglog" } //remove constant or not /* if "`fitcommand'" == "meqrlogit" { local minconstant "noconstant" } else { //remove mu from the expression since constant is present gettoken mu regexpression : regexpression }*/ //Fit the FE model if ("`model'" != "random") { if "`link'" == "logit" { capture noisily binreg `1' `regexpression' if `touse', noconstant n(`2') ml `modelopts' l(`level') } else { capture noisily glm `1' `regexpression' if `touse', noconstant family(binomial `2') link(cloglog) ml `modelopts' l(`level') } local success = _rc } //Fit the ME model if ("`model'" == "random") { if strpos(`"`modelopts'"', "intpoi") == 0 { qui count if `touse' if `=r(N)' < 7 { local ipoints = `"intpoints(`=r(N)')"' } } else { qui count if `touse' local nobs =r(N) local oldopts `"`modelopts'"' local modelopts while `"`oldopts'"' != "" { gettoken first oldopts : oldopts if strpos(`"`first'"', "intpoi")!= 0 { local b1 = strpos(`"`first'"', "(") + 1 local b2 = strpos(`"`first'"', ")") local oldpoints = substr(`"`first'"', `b1', `=`b2'-`b1'') if `oldpoints' > `nobs' { local ipoints = `"intpoints(`nobs')"' } local first } local modelopts "`modelopts' `first'" if "`first'" == "" { local local modelopts "`modelopts' `oldopts'" continue, break } } } //First trial #delim ; capture noisily `fitcommand' (`1' `regexpression' if `touse', noconstant)|| (`sid': `varx' , `cov') `nested' , binomial(`2') `ipoints' `modelopts' l(`level') ; #delimit cr local success = _rc local converged = e(converged) if `success' != 0 { //First fit laplace to get better starting values noi di _n"*********************************** ************* ***************************************" noi di as txt _n "Just a moment - Obtaining better initial values " noi di "*********************************** ************* ***************************************" local lapsuccess 1 if "`fitcommand'" == "meqrlogit" { local laplace "laplace" } else { local laplace "intmethod(laplace)" } if (strpos(`"`modelopts'"', "from") == 0) { #delim ; capture noisily `fitcommand' (`1' `regexpression' if `touse', noconstant)|| (`sid': `varx' , `cov') `nested' , binomial(`2') `laplace' l(`level') ; #delimit cr local lapsuccess = _rc //0 is success local converged = e(converged) if `lapsuccess' == 0 { qui estimates table tempname initmat mat `initmat' = r(coef) local ninits = rowsof(`initmat') forvalues e = 1(1)`ninits' { local init = `initmat'[`e', 1] if `init' != .b { if `e' == 1 { local inits = `"`init'"' } else { local inits = `"`inits', `init'"' } } } mat `initmat' = (`inits') } local inits = `"from(`initmat', copy)"' } if strpos(`"`modelopts'"', "iterate") == 0 { local modelopts = `"iterate(30) `modelopts'"' } //second trial with initial values #delim ; capture noisily `fitcommand' (`1' `regexpression' if `touse', noconstant)|| (`sid': `varx', `cov') `nested' , binomial(`2') `ipoints' `modelopts' `inits' l(`level') ; #delimit cr local success = _rc local converged = e(converged) } //Try to refineopts 3 times if strpos(`"`modelopts'"', "refineopts") == 0 & ("`fitcommand'" == "meqrlogit") { local try = 1 while `try' < 3 & `converged' == 0 { #delim ; capture noisily `fitcommand' (`1' `regexpression' if `touse', noconstant)|| (`sid': `varx' , `cov') `nested' , binomial(`2') `ipoints' `modelopts' l(`level') refineopts(iterate(`=10 * `try'')); #delimit cr local success = _rc local converged = e(converged) local try = `try' + 1 } } *Try matlog if still difficult if (strpos(`"`modelopts'"', "matlog") == 0) & ("`fitcommand'" == "meqrlogit") & ((`converged' == 0) | (`success' != 0)) { if strpos(`"`modelopts'"', "refineopts") == 0 { local refineopts = "refineopts(iterate(50))" } #delim ; capture noisily `fitcommand' (`1' `regexpression' if `touse', noconstant )|| (`sid': `varx' , `cov') `nested' , binomial(`2') `ipoints' `modelopts' l(`level') `refineopts' matlog; #delimit cr local success = _rc local converged = e(converged) } } *If not converged, exit and offer possible solutions if `success' != 0 { di as error "Model fitting failed" di as error "Try fitting a simpler model or better model option specifications" exit `success' } end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: metadta_PROPCI +++++++++++++++++++++++++ CI for proportions ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop metapreg_propci program define metapreg_propci version 14.1 syntax varlist [if] [in], p(name) se(name)lowerci(name) upperci(name) [cimethod(string) level(real 95)] qui { tokenize `varlist' gen `p' = . gen `lowerci' = . gen `upperci' = . gen `se' = . count `if' `in' forvalues i = 1/`r(N)' { local N = `1'[`i'] local n = `2'[`i'] cii proportions `N' `n', `cimethod' level(`level') replace `p' = r(proportion) in `i' replace `lowerci' = r(lb) in `i' replace `upperci' = r(ub) in `i' replace `se' = r(se) in `i' } } end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: LONGSETUP +++++++++++++++++++++++++ Transform data to long format +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop longsetup program define longsetup version 14.1 syntax varlist, rid(name) assignment(name) event(name) total(name) idpair(name) [ mcbnetwork pcbnetwork abnetwork general comparative ] qui { tokenize `varlist' if "`mcbnetwork'" != "" { /*The four variables should contain numbers*/ forvalue i=1(1)4 { capture confirm numeric var ``i'' if _rc != 0 { di as error "The variable ``i'' must be numeric" exit } } /*4 variables per study : a b c d*/ gen `event'1 = `1' + `2' /* a + b */ gen `event'0 = `1' + `3' /* a + c */ gen `total'1 = `1' + `2' + `3' + `4' /* n */ gen `total'0 = `1' + `2' + `3' + `4' /* n */ gen `assignment'1 = `5' gen `assignment'0 = `6' } else { /*pcbnetwork: The three variables should contain numbers*/ forvalue i=1(1)3 { capture confirm numeric var ``i'' if _rc != 0 { di as error "The variable ``i'' must be numeric" exit } } /*3 variables per study : n1 n2 N*/ gen `event'1 = `1' /* n1 */ gen `event'0 = `2' /* n2 */ gen `total'1 = `3' /* N */ gen `total'0 = `3' /* N */ gen `assignment'1 = `4' gen `assignment'0 = `5' } gen `rid' = _n reshape long `event' `total' `assignment', i(`rid') j(`idpair') } end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: WIDESETUP +++++++++++++++++++++++++ Transform data to wide format +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop widesetup program define widesetup, rclass version 14.1 syntax varlist, sid(varlist) idpair(varname) [sortby(varlist) jvar(varname) mcbnetwork pcbnetwork abnetwork general comparative] qui{ tokenize `varlist' tempvar modey diffy *if "`mcbnetwork'" == "" { tempvar jvar gen `jvar' = `idpair' - 1 *} /*Check for varying variable and store them*/ ds local vnames = r(varlist) local vlist foreach v of local vnames { cap drop `modey' `diffy' bysort `sid': egen `modey' = mode(`v'), minmode egen `diffy' = diff(`v' `modey') sum `diffy' local sumy = r(sum) local in 0 foreach str of local varlist { if `in' { continue, break } if "`v'" =="`str'" { local in 1 } } if (!`in') & (`sumy' > 0) & "`v'" != "`jvar'" & "`v'" != "`idpair'" { local vlist "`vlist' `v'" } } cap drop `modey' `diffy' sort `sid' `jvar' `sortby' /*2 variables per study : n N*/ reshape wide `1' `2' `idpair' `vlist', i(`sid') j(`jvar') local cc0 = `idpair'0[1] local cc1 = `idpair'1[1] local idpair0 : lab `idpair' `cc0' local idpair1 : lab `idpair' `cc1' return local vlist = "`vlist'" return local cc0 = "`idpair0'" return local cc1 = "`idpair1'" } end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: PREP4SHOW +++++++++++++++++++++++++ Prepare data for display table and graph +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop prep4show program define prep4show version 14.1 #delimit ; syntax varlist, [poprrout(name) rrout(name) poporout(name) orout(name) popabsout(name) absout(name) absoutp(name) sortby(varlist) by(varname) hetout(name) model(string) prediction groupvar(varname) se(varname) summaryonly nooverall nosubgroup outplot(string) grptotal(name) download(string asis) indvars(varlist) depvars(varlist) dp(integer 2) stratify pcont(integer 0) level(integer 95) comparative abnetwork general pcbnetwork mcbnetwork ] ; #delimit cr tempvar expand serror tokenize `varlist' local id = "`1'" local use = "`2'" local label = "`3'" local es = "`4'" local lci = "`5'" local uci = "`6'" local modeles = "`7'" local modellci = "`8'" local modeluci = "`9'" if "`se'" !="" { gen `serror' = `se' } else{ gen `serror' = 0 } qui { gen `expand' = 1 //Groups if "`groupvar'" != "" { bys `groupvar' : egen `grptotal' = count(`id') //# studies in each group gsort `groupvar' `sortby' `id' bys `groupvar' : replace `expand' = 1 + 1*(_n==1) + 3*(_n==_N) expand `expand' gsort `groupvar' `sortby' `id' `expand' bys `groupvar' : replace `use' = -2 if _n==1 //group label bys `groupvar' : replace `use' = 2 if _n==_N-2 //summary bys `groupvar' : replace `use' = 4 if _n==_N-1 //prediction bys `groupvar' : replace `use' = 0 if _n==_N //blank */ replace `id' = `id' + 1 if `use' == 1 replace `id' = `id' + 2 if `use' == 2 //summary replace `id' = `id' + 3 if `use' == 4 //Prediction replace `id' = `id' + 4 if `use' == 0 //blank *replace `label' = "Summary" if `use' == 2 replace `label' = "Group Mean" if `use' == 2 replace _WT = . if `use' == 2 qui label list `groupvar' local nlevels = r(max) forvalues l = 1/`nlevels' { if "`outplot'" == "abs" { if "`model'" == "hexact" { local S_1 = `absout'[`=`pcont' +`l'', 1] local S_3 = `absout'[`=`pcont' +`l'', 5] local S_4 = `absout'[`=`pcont' +`l'', 6] } else { local S_1 = `popabsout'[`l', 1] local S_3 = `popabsout'[`l', 4] local S_4 = `popabsout'[`l', 5] } if "`prediction'" != "" { local S_5 = `absoutp'[`l', 1] local S_6 = `absoutp'[`l', 2] } if "`model'" == "random" & "`indvars'" == "" & "`stratify'" !="" { local isq = `hetout'[`l', 5] local phet = `hetout'[`l', 3] *replace `label' = "Summary (Isq = " + string(`isq', "%10.`=`dp''f") + "%, p = " + string(`phet', "%10.`=`dp''f") + ")" if `use' == 2 & `groupvar' == `l' & `grptotal' > 2 replace `label' = "Group Mean (Isq = " + string(`isq', "%10.`=`dp''f") + "%, p = " + string(`phet', "%10.`=`dp''f") + ")" if `use' == 2 & `groupvar' == `l' & `grptotal' > 2 } } else { if "`outplot'" == "rr" { local S_1 = `poprrout'[`l', 1] local S_3 = `poprrout'[`l', 4] local S_4 = `poprrout'[`l', 5] } if "`outplot'" == "or" { local S_1 = `poporout'[`l', 1] local S_3 = `poporout'[`l', 4] local S_4 = `poporout'[`l', 5] } } local lab:label `groupvar' `l' replace `label' = "`groupvar' = `lab'" if `use' == -2 & `groupvar' == `l' & (("`abnetwork'" == "") |("`outplot'" == "abs" & "`abnetwork'" != "")) replace `label' = "`lab'" if `use' == 2 & `groupvar' == `l' & "`outplot'" != "abs" & "`abnetwork'" != "" replace `es' = `S_1' if `use' == 2 & `groupvar' == `l' replace `lci' = `S_3' if `use' == 2 & `groupvar' == `l' replace `uci' = `S_4' if `use' == 2 & `groupvar' == `l' //Predictions if "`outplot'" == "abs" & "`prediction'" != "" { replace `lci' = `S_5' if `use' == 4 & `groupvar' == `l' replace `uci' = `S_6' if `use' == 4 & `groupvar' == `l' } //Weights sum _WT if `use' == 1 & `groupvar' == `l' local groupwt = r(sum) replace _WT = `groupwt' if `use' == 2 & `groupvar' == `l' } } else { egen `grptotal' = count(`id') //# studies total } //Overall if "`overall'" == "" { gsort `groupvar' `sortby' `id' replace `expand' = 1 + 3*(_n==_N) expand `expand' gsort `groupvar' `sortby' `id' `expand' replace `use' = 4 if _n==_N //Prediction replace `use' = 3 if _n==_N-1 //Overall replace `use' = 0 if _n==_N-2 //blank replace `id' = `id' + 3 if _n==_N //Prediction replace `id' = `id' + 2 if _n==_N-1 //Overall replace `id' = `id' + 1 if _n==_N-2 //blank //Fill in the right info if "`outplot'" == "abs" { if "`model'" == "hexact" { local nrows = rowsof(`absout') local S_1 = `absout'[`nrows', 1] local S_3 = `absout'[`nrows', 5] local S_4 = `absout'[`nrows', 6] } else { local nrows = rowsof(`popabsout') local S_1 = `popabsout'[`nrows', 1] local S_3 = `popabsout'[`nrows', 4] local S_4 = `popabsout'[`nrows', 5] } //predictions if "`prediction'" != "" { local nrows = rowsof(`absoutp') local S_5 = `absoutp'[`nrows', 1] local S_6 = `absoutp'[`nrows', 2] } } else { if "`outplot'" == "rr" { local nrows = rowsof(`poprrout') local S_1 = `poprrout'[`nrows', 1] local S_3 = `poprrout'[`nrows', 4] local S_4 = `poprrout'[`nrows', 5] } if "`outplot'" == "or" { local nrows = rowsof(`poporout') local S_1 = `poporout'[`nrows', 1] local S_3 = `poporout'[`nrows', 4] local S_4 = `poporout'[`nrows', 5] } } if "`model'" == "random" & "`indvars'" == "" & "`outplot'" == "abs" { local nrows = rowsof(`hetout') local isq = `hetout'[`nrows', 5] local phet = `hetout'[`nrows', 3] *replace `label' = "Overall (Isq = " + string(`isq', "%10.`=`dp''f") + "%, p = " + string(`phet', "%10.`=`dp''f") + ")" if `use' == 3 replace `label' = "Population Mean (Isq = " + string(`isq', "%10.`=`dp''f") + "%, p = " + string(`phet', "%10.`=`dp''f") + ")" if `use' == 3 } else { *replace `label' = "Overall" if `use' == 3 replace `label' = "Population Mean" if `use' == 3 } replace `es' = `S_1' if `use' == 3 replace `lci' = `S_3' if `use' == 3 replace `uci' = `S_4' if `use' == 3 replace _WT = . if (`use' == 3) & ("`stratify'" != "") replace _WT = 100 if (`use' == 3) & ("`stratify'" == "") //Predictions if "`outplot'" == "abs" & "`prediction'" != "" { replace `lci' = `S_5' if _n==_N replace `uci' = `S_6' if _n==_N } } count if `use'==1 replace `grptotal' = `=r(N)' if `use'==3 replace `grptotal' = `=r(N)' if _n==_N replace `label' = "" if `use' == 0 replace `es' = . if `use' == 0 | `use' == -2 | `use' == 4 //4 is prediction replace `lci' = . if `use' == 0 | `use' == -2 replace `uci' = . if `use' == 0 | `use' == -2 gsort `groupvar' `sortby' `id' replace `label' = "Predictive t Interval" if `use' == 4 & "`model'" == "random" replace `label' = "t Interval" if `use' == 4 & "`model'" != "random" } qui { replace `modeles' = . if `use' != 1 replace `modellci' = . if `use' != 1 replace `modeluci' = . if `use' != 1 replace _WT = . if `use'==0 | `use'==-2 | `use'==4 } if `"`download'"' != "" { local ZOVE -invnorm((100-`level')/200) preserve qui { cap drop _ES _SE _LCI _UCI _USE _LABEL _MODELES _MODELLCI _MODELUCI gen _ES = `es' gen _SE = `serror' gen _LCI = `lci' gen _UCI = `uci' gen _USE = `use' gen _LABEL = `label' gen _ID = `id' gen _MODELES = `modeles' gen _MODELLCI = `modellci' gen _MODELUCI = `modeluci' replace _ID = _n replace _SE = ( `uci' - `lci')/(2*`ZOVE') if _SE == 0 *keep if _USE == 1 keep `depvars' `indvars' `groupvar' _ES _SE _LCI _UCI _USE _ESAMPLE _WT _LABEL _ID _MODELES _MODELLCI _MODELUCI } di "*********************************************************************" di _n "Saving data....." di "Note: For n=N or n=0, _SE=0" di "and approximated with _SE = (_UCI – _LCI)/(2*Z(`level'))" noi save `download', replace restore } qui { if "`abnetwork'" == "" | ("`abnetwork'" != "" & "`outplot'" == "abs") { drop if (`use' == 2 | `use' == 3) & (`grptotal' == 1) //drop summary if 1 study } drop if (`use' == 1 & "`summaryonly'" != "" & `grptotal' > 1) | (`use' == 2 & "`subgroup'" != "") | (`use' == 3 & "`overall'" != "") | (`use' == 4 & "`prediction'" == "") //Drop unnecessary rows if "`abnetwork'" != "" & "`outplot'" != "abs" { drop if `use' == 1 | `use' == -2 replace `use' = 1 if `use' == 2 } //Remove weight if 1 study - Show the weight; otherwise gives the impression the study did not contribute *qui replace _WT= . if (`use' == 1) & (`grptotal' == 1) gsort `groupvar' `sortby' `id' replace `id' = _n gsort `id' } end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: DISPTAB +++++++++++++++++++++++++ Prepare data for display table and graph +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop disptab program define disptab version 14.1 #delimit ; syntax varlist, [nosubgroup nooverall level(integer 95) sumstat(string asis) model(string) dp(integer 2) power(integer 0) nowt smooth icimethod(string) ocimethod(string) groupvar(varname) comparative abnetwork general pcbnetwork mcbnetwork outplot(string) summaryonly] ; #delimit cr tempvar rid id use label es lci uci grptotal modeles modellci modeluci tokenize `varlist' qui { gen `id' = `1' gen `use' = `2' gen `label' = `3' gen `es' = `4' gen `lci' = `5' gen `uci' = `6' gen `grptotal' = `7' if "`smooth'" !="" { gen `modeles' = `8' gen `modellci' = `9' gen `modeluci' = `10' } } preserve tempvar tlabellen //study label local studylb: variable label `label' if "`studylb'" == "" { local studylb "Study" } local studylen = strlen("`studylb'") qui gen `tlabellen' = strlen(`label') qui summ `tlabellen' if `use' == 1 local nlen = `=max(r(max), 15) + 2' local nlens = strlen("`sumstat'") local level: displ %2.0f `level' local start: displ %2.0f `=`nlen'/2 - `studylen'/2 + 2' di as res _n "***********************************************************************" if "`smooth'" != "" { di as res "{pmore2} Study specific `sumstat' : Observed (Smoothed) {p_end}" } else { di as res "{pmore2} Study specific `sumstat' {p_end}" } di as res "***********************************************************************" local colstat = int(`=`nlen' + `nlens'*0.5') if "`wt'" =="" { local dispwt "% Weight" } //Find the length of the estimates qui { tempvar hold holdstr slimest gen `hold' = `uci'*(10^`power') tostring `hold', gen(`holdstr') format(%10.`dp'f) force gen `slimest' = strlen(strltrim(`holdstr')) sum `slimest' local est_i_len = r(max) } if "`smooth'" !="" { local open " (" local close ")" local aesclose "%1s" local aes "%`=`est_i_len''.`=`dp''f" } if "`summaryonly'" == "" { if "`smooth'" == "" { local citext "- `icimethod' CI -" } else { local citext "- `icimethod' (Wald) CI - " } } else { local citext "- Centile CI - " } if "`outplot'" == "abs" { if "`summaryonly'" == "" { if "`smooth'" == "" { local citext "- `icimethod' CI -" } else { local citext "- `icimethod' (Wald) CI - " } } else { local citext "- Centile CI - " } } else { if "`smooth'" == "" { local citext "- `icimethod' CI -" } else { local citext "- `icimethod' (Centile) CI - " } } if "`outplot'" =="abs" & "`comparative'" != "" { qui { if "`smooth'" == "" { keep `id' `use' `label' `es' `lci' `uci' `grptotal' `groupvar' _WT } else { keep `id' `use' `label' `es' `lci' `uci' `grptotal' `modeles' `modellci' `modeluci' `groupvar' _WT } bys `groupvar': egen `rid' = seq() replace `groupvar' = `groupvar' - 1 duplicates drop `groupvar' if `use'==0,force if "`smooth'" == "" { reshape wide `id' `label' `es' `lci' `uci' `grptotal' _WT, i(`rid') j(`groupvar') } else { reshape wide `id' `label' `es' `lci' `uci' `grptotal' `modeles' `modellci' `modeluci' _WT, i(`rid') j(`groupvar') } local label0 = `label'0[1] local label1 = `label'1[1] local nlen0 = strlen("`label0'") local nlen1 = strlen("`label1'") replace _WT0 = _WT0 + _WT1 rename _WT0 _WT } di _n as txt _col(`nlen') "| " _skip(`=21 - round(`nlen0'/2)') "`label0'" /// _skip(`=47 - (21 - round(`nlen0'/2)) - `nlen0' - 1') "| " _skip(`=21 - round(`nlen1'/2)') "`groupvar' = `label1'" _cont di _n as txt _col(`start') "`studylb'" _col(`nlen') "| " _skip(5) "Estimate" /// _skip(5) "[`level'% Conf. Interval]" /// _skip(9) "| " _skip(5) "Estimate" /// _skip(5) "[`level'% Conf. Interval]" /// _skip(12) "| " _skip(3) "`dispwt'" di _dup(`=`nlen'-1') "-" "+" _dup(48) "-" "+" _dup(51) "-" "+" _dup(10) "-" qui count local N = r(N) forvalues i = 1(1)`N' { //Weight if "`wt'" =="" { local ww = _WT[`i'] } //Studies -- Control if ((`use'[`i'] ==1)) { //Smooth estimates if "`smooth'" !="" { local mes0 "`modeles'0[`i']*(10^`power')" local mlci0 "`modellci'0[`i']*(10^`power')" local muci0 "`modeluci'0[`i']*(10^`power')" } di _col(2) as txt `label'1[`i'] _col(`nlen') "| " /// _skip(2) as res %5.`=`dp''f `es'1[`i']*(10^`power') "`open'" `aes' `mes0' "`close'" /// _col(`=`nlen' + 20') %5.`=`dp''f `lci'1[`i']*(10^`power') "`open'" `aes' `mlci0' `aesclose' "`close'" /// _skip(5) %5.`=`dp''f `uci'1[`i']*(10^`power') "`open'" `aes' `muci0' `aesclose' "`close'" _cont } //studies - Treatment if (`use'[`i'] ==1 ) { //Smooth estimates if "`smooth'" !="" { local mes1 "`modeles'1[`i']*(10^`power')" local mlci1 "`modellci'1[`i']*(10^`power')" local muci1 "`modeluci'1[`i']*(10^`power')" } di as txt _col(`=`nlen' + 45') "| " /// _skip(2) as res %5.`=`dp''f `es'0[`i']*(10^`power') "`open'" `aes' `mes1' "`close'" /// _col(`=`nlen' + 72') %5.`=`dp''f `lci'0[`i']*(10^`power') "`open'" `aes' `mlci1' `aesclose' "`close'" /// _skip(5) %5.`=`dp''f `uci'0[`i']*(10^`power') "`open'" `aes' `muci1' `aesclose' "`close'" _col(`=`nlen' + 90') as txt "| " _skip(3) as res %5.`=`dp''f `ww' } //Summaries if (`use'[`i']== 2) { di as res _dup(`=`nlen'-1') "-" "+" _dup(48) "-" "+" _dup(51) "-" "+" _dup(10) "-" di _col(2) as txt `label'0[`i'] _col(`nlen') "| " /// _skip(`=3 + 5') as res %5.`=`dp''f `es'1[`i']*(10^`power') /// _col(`=`nlen' + 20 + 6') %5.`=`dp''f `lci'1[`i']*(10^`power') /// _skip(`=5 + 7') %5.`=`dp''f `uci'1[`i']*(10^`power') /// as txt _col(`=`nlen' + 45 + 4') "| " /// _skip(`=3 + 5') as res %5.`=`dp''f `es'0[`i']*(10^`power') /// _col(`=`nlen' + 66 + 12') %5.`=`dp''f `lci'0[`i']*(10^`power') /// _skip(`=5 + 7') %5.`=`dp''f `uci'0[`i']*(10^`power') /// _col(`=`nlen' + 90 + 8') as txt " | " _skip(2) as res %5.`=`dp''f `ww' } //Blanks if (`use'[`i'] == 0 ){ di as res _dup(`=`nlen'-1') "-" "+" _dup(48) "-" "+" _dup(51) "-" "+" _dup(10) "-" } } } else { if "`smooth'" !="" { /* di _n as txt _col(`start') "`studylb'" _col(`nlen') "| " _skip(5) "Estimate" /// _col(`=`nlen' + `nlens' + 20') "Lower - `icimethod' (Wald) CI- Upper" _skip(10) "`dispwt'" */ di _n as txt _col(`start') "`studylb'" _col(`nlen') "| " _skip(5) "Estimate" /// _col(`=`nlen' + `nlens' + 20') "`=(100-`level')/2'% "`"`citext'"'" `=100 - (100-`level')/2'%" _col(`=`nlen' + `nlens' + 60') "`dispwt'" local colwt = int(`=`nlen' + `nlens' + 55') } else{ di _n as txt _col(`start') "`studylb'" _col(`nlen') "| " _skip(5) "Estimate" /// _col(`=`nlen' + `nlens' + 10') "`=(100-`level')/2'% "`"`citext'"'" `=100 - (100-`level')/2'%" _col(`=`nlen' + `nlens' + 40') "`dispwt'" local colwt = int(`=`nlen' + `nlens' + 35') } di _dup(`=`nlen'-1') "-" "+" _dup(57) "-" qui count local N = r(N) forvalues i = 1(1)`N' { //Weight if "`wt'" =="" { local ww = _WT[`i'] } //Group labels if ((`use'[`i']== -2)){ di _col(2) as txt `label'[`i'] _col(`nlen') "| " } //Studies if ((`use'[`i'] ==1)) { //Smooth estimates if "`smooth'" !="" { local mes "`modeles'[`i']*(10^`power')" local mlci "`modellci'[`i']*(10^`power')" local muci "`modeluci'[`i']*(10^`power')" } di _col(2) as txt `label'[`i'] _col(`nlen') "| " /// _col(`colstat') as res %10.`=`dp''f `es'[`i']*(10^`power') "`open'" `aes' `mes' "`close'" /// _col(`=`nlen' + `nlens' + 5') %10.`=`dp''f `lci'[`i']*(10^`power') "`open'" `aes' `mlci' `aesclose' "`close'" /// _skip(5) %10.`=`dp''f `uci'[`i']*(10^`power') "`open'" `aes' `muci' "`close'" _col(`colwt') %10.`=`dp''f `ww' } //Summaries if ( (`use'[`i']== 3) | ((`use'[`i']== 2) & (`grptotal'[`i'] > 1))){ if ((`use'[`i']== 2) & (`grptotal'[`i'] > 1)) { di _col(2) as txt _col(`nlen') "| " } if (`use'[`i']== 2) { local sumtext = "Group Mean" } else { local sumtext = "Population Mean" } if "`smooth'" != "" { di _col(2) as txt "`sumtext'" _col(`nlen') "| " /// _col(`=`colstat'+8') as res %`=`est_i_len''.`=`dp''f `es'[`i']*(10^`power') /// _col(`=`nlen' + `nlens' + 22') %`=`est_i_len''.`=`dp''f `lci'[`i']*(10^`power') /// _skip(14) %`=`est_i_len''.`=`dp''f `uci'[`i']*(10^`power') _col(`colwt') %10.`=`dp''f `ww' } else { di _col(2) as txt "`sumtext'" _col(`nlen') "| " /// _col(`colstat') as res %10.`=`dp''f `es'[`i']*(10^`power') /// _col(`=`nlen' + `nlens' + 5') %10.`=`dp''f `lci'[`i']*(10^`power') /// _skip(5) %10.`=`dp''f `uci'[`i']*(10^`power') _col(`colwt') %10.`=`dp''f `ww' } } //Blanks if (`use'[`i'] == 0 ){ di as txt _dup(`=`nlen'-1') "-" "+" _dup(57) "-" } } } restore end /*++++++++++++++++ SUPPORTING FUNCTIONS: BUILDEXPRESSIONS +++++++++++++++++++++ buildexpressions the regression and estimation expressions +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop buildregexpr program define buildregexpr, rclass version 13.1 syntax varlist, [interaction alphasort mcbnetwork pcbnetwork abnetwork general comparative ipair(varname) baselevel(string) studyid(varname) ] tempvar holder tokenize `varlist' if "`mcbnetwork'`pcbnetwork'" == "" { macro shift 2 local regressors "`*'" } else { if "`mcbnetwork'" != "" { local index = "`5'" local comparator = "`6'" macro shift 6 } else { local index = "`4'" local comparator = "`5'" macro shift 5 } local regressors "`*'" my_ncod `holder', oldvar(`index') drop `index' rename `holder' `index' my_ncod `holder', oldvar(`ipair') drop `ipair' rename `holder' `ipair' my_ncod `holder', oldvar(`comparator') drop `comparator' rename `holder' `comparator' } local p: word count `regressors' local catreg " " local contreg " " if ("`general'`comparative'" != "") { local regexpression = "mu" } else if "`mcbnetwork'`pcbnetwork'" != "" { if "`interaction'" != "" { local regexpression = "ibn.`ipair'#ibn.`comparator' i.`index'" //nulllify local interaction } else { local regexpression = "mu i.`ipair' i.`index'" } } else { *abnetwork local regexpression } local basecode 1 tokenize `regressors' forvalues i = 1(1)`p' { capture confirm numeric var ``i'' if _rc != 0 { if "`alphasort'" != "" { sort ``i'' } my_ncod `holder', oldvar(``i'') drop ``i'' rename `holder' ``i'' local prefix_`i' "i" } else { local prefix_`i' "c" } if "`abnetwork'" != "" & `i'==1 { local prefix_`i' "ibn" if "`baselevel'" != "" { //Find the base level qui label list ``i'' local nlevels = r(max) local found = 0 local level 1 while !`found' & `level' < `=`nlevels'+1' { local lab:label ``i'' `level' if "`lab'" == "`baselevel'" { local found = 1 local basecode `level' } local ++level } } } /*Add the proper expression for regression*/ local regexpression = "`regexpression' `prefix_`i''.``i''" if `i' > 1 & "`interaction'" != "" { local regexpression = "`regexpression' `prefix_`i''.``i''#`prefix_1'.`1'" } if "``i''" == "`studyid'" { continue } //Pick out the interactor variable if `i' == 1 & "`interaction'" != "" { local varx = "``i''" local typevarx = "`prefix_`i''" } *if (`i' > 1 & "`interaction'" != "" ) | "`interaction'" == "" { //store the rest of variables if strpos("`prefix_`i''","i") != 0 { local catreg "`catreg' ``i''" } else { local contreg "`contreg' ``i''" } *} } if "`interaction'" != "" { return local varx = "`varx'" return local typevarx = "`typevarx'" } return local regexpression = "`regexpression'" return local catreg = "`catreg'" return local contreg = "`contreg'" return local basecode = "`basecode'" end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: ESTP +++++++++++++++++++++++++ estimate log odds or proportions after modelling +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop estp program define estp, rclass version 14.1 syntax, estimates(string) studyid(varname) [expit DP(integer 2) model(string) varx(varname) typevarx(string) regexpression(string) /// comparator(varname) cimethod(string) mcbnetwork pcbnetwork abnetwork general comparative stratify interaction /// catreg(varlist) contreg(varlist) power(integer 0) level(integer 95) by(varname) link(string) ] tempname coefmat outmatrix outmatrixp matrixout bycatregmatrixout catregmatrixout contregmatrixout row outmatrixr overall Vmatrix byVmatrix tokenize `regexpression' if "`mcbnetwork'`pcbnetwork'" != "" { if "`interaction'" != "" { tokenize `2', parse(".") } else { tokenize `3', parse(".") } local index "`3'" local catreg = "`3' `catreg'" local varx //nullify if "`by'" != "`comparator'" { *local catreg = "`comparator' `catreg'" } } if "`abnetwork'" != "" { tokenize `2', parse(".") local assignment "`3'" local catreg = "`3' `catreg'" } if "`interaction'" != "" & "`typevarx'" == "i" { local idpairconcat "#`varx'" } if "`typevarx'" == "i" { if "`catreg'" == "" { local catreg = "`varx'" } } else { if "`contreg'" == "" { local contreg = "`varx'" } } //Expression for logodds prediction if "`link'" == "cloglog" { local expression "exp(logit(invcloglog(predict(xb))))" } else if "`link'" == "loglog" { local expression "exp(-logit(invcloglog(predict(xb))))" } else { local expression "exp(predict(xb))" } local invfn "invlogit" if "`idpairconcat'" != ""{ local marginlist = `"`varx'"' } else { local marginlist } while "`catreg'" != "" { tokenize `catreg' if ("`1'" != "`by'" & "`by'" != "") | "`by'" =="" { if ("`1'" != "`studyid'") { if "`idpairconcat'" != ""{ local marginlist = `"`marginlist' `1'"' } local marginlist = `"`marginlist' `1'`idpairconcat'"' } } macro shift local catreg `*' } qui estimates restore `estimates' local df = e(N) - e(k) mat `coefmat' = e(b) local predcmd = e(predict) if "`model'" == "random" { local npar = colsof(`coefmat') if "`predcmd'" == "meqrlogit_p" { local scalefn "exp" local scalepow "2" } else { local scalepow "1" } if "`abnetwork'`cov'" == "" { local TAU21 = `scalefn'(`coefmat'[1, `npar'])^`scalepow' //Between study variance 1 local TAU22 = 0 } else if "`abnetwork'" != "" { local TAU21 = `scalefn'(`coefmat'[1, `=`npar'-1'])^`scalepow' //Between study variance 1 local TAU22 = `scalefn'(`coefmat'[1, `npar'])^`scalepow' //Between study variance 2 } else if "`cov'" != "" { local TAU21 = `rosevar'[1, 1] local TAU22 = `rosevar'[2, 2] if "`cov'" == "unstructured" { local rho = tanh(`rawvar'[1, 2]) } } } else { local TAU21 = 0 local TAU22 = 0 } /* if "`model'" == "random" { local npar = colsof(`coefmat') if "`abnetwork'" == "" { local TAU21 = exp(`coefmat'[1, `npar'])^2 //Between study variance 1 local TAU22 = 0 } else { local TAU21 = exp(`coefmat'[1, `=`npar'-1'])^2 //Between study variance 1 local TAU22 = exp(`coefmat'[1, `npar'])^2 //Between study variance 2 } } else { local TAU21 = 0 local TAU22 = 0 } */ local byncatreg 0 if "`by'" != "" & "`stratify'" == "" { qui margin , `expression' over(`by') level(`level') mat `bycatregmatrixout' = r(table)' mat `byVmatrix' = r(V) mat `bycatregmatrixout' = `bycatregmatrixout'[1..., 1..6] local byrnames :rownames `bycatregmatrixout' local byncatreg = rowsof(`bycatregmatrixout') } if "`abnetwork'`mcbnetwork'`pcbnetwork'" == "" { local grand "grand" local Overall "Overall" } if "`comparative'" != "" & "`stratify'" != "" { local grand local Overall } local ncatreg 0 //Overall if "`marginlist'" != "" | ( "`marginlist'" == "" & "`abnetwork'`mcbnetwork'`pcbnetwork'" == "" ) { qui margin `marginlist', `expression' `grand' level(`level') mat `catregmatrixout' = r(table)' mat `Vmatrix' = r(V) mat `catregmatrixout' = `catregmatrixout'[1..., 1..6] local rnames :rownames `catregmatrixout' local ncatreg = rowsof(`catregmatrixout') } local init 1 local ncontreg 0 local contrownames = "" if "`contreg'" != "" { foreach v of local contreg { summ `v', meanonly local vmean = r(mean) qui margin, `expression' at(`v'=`vmean') level(`level') mat `matrixout' = r(table)' mat `matrixout' = `matrixout'[1..., 1..6] if `init' { local init 0 mat `contregmatrixout' = `matrixout' } else { mat `contregmatrixout' = `contregmatrixout' \ `matrixout' } local contrownames = "`contrownames' `v'" local ++ncontreg } } mat `outmatrixp' = J(`=`byncatreg' + `ncatreg'', 2, .) if "`expit'" != "" { forvalues r = 1(1)`byncatreg' { mat `outmatrixp'[`r', 1] = `invfn'(`bycatregmatrixout'[`r',1] - invttail((`df'), 0.5-`level'/200) * sqrt(`bycatregmatrixout'[`r',2]^2 + `TAU21'^2 + `TAU22'^2)) mat `outmatrixp'[`r', 2] = `invfn'(`bycatregmatrixout'[`r',1] + invttail((`df'), 0.5-`level'/200)* sqrt(`bycatregmatrixout'[`r',2]^2 + `TAU21'^2 + `TAU22'^2)) } forvalues r = `=`byncatreg' + 1'(1)`=`byncatreg' + `ncatreg''{ mat `outmatrixp'[`r', 1] = `invfn'(`catregmatrixout'[`=`r' - `byncatreg'', 1] - invttail((`df'), 0.5-`level'/200) * sqrt(`catregmatrixout'[`=`r' - `byncatreg'', 2]^2 + `TAU21'^2 + `TAU22'^2)) mat `outmatrixp'[`r', 2] = `invfn'(`catregmatrixout'[`=`r' - `byncatreg'', 1] + invttail((`df'), 0.5-`level'/200)* sqrt(`catregmatrixout'[`=`r' - `byncatreg'', 2]^2 + `TAU21'^2 + `TAU22'^2)) } } if (`ncatreg' > 0 & `byncatreg' > 0) { mat `matrixout' = `bycatregmatrixout' \ `catregmatrixout' } if (`ncatreg' > 0 & `byncatreg' == 0) { mat `matrixout' = `catregmatrixout' } if (`ncatreg' == 0 & `byncatreg' > 0) { mat `matrixout' = `bycatregmatrixout' } if (`ncontreg' > 0) { mat `matrixout' = `contregmatrixout' \ `matrixout' } //t distribution if "`cimethod'" == "t" { forvalues r = 1(1)`=`byncatreg' + `ncatreg' + `ncontreg'' { local tstat = `matrixout'[`r', 3] mat `matrixout'[`r', 4] = ttail(`df', abs(`tstat'))*2 mat `matrixout'[`r', 5] = `matrixout'[`r', 1] - invttail((`df'), 0.5-`level'/200) * `matrixout'[`r', 2] mat `matrixout'[`r', 6] = `matrixout'[`r', 1] + invttail((`df'), 0.5-`level'/200) * `matrixout'[`r', 2] } } if "`expit'" != "" { forvalues r = 1(1)`=`byncatreg' + `ncatreg' + `ncontreg'' { mat `matrixout'[`r', 1] = `invfn'(`matrixout'[`r', 1]) mat `matrixout'[`r', 5] = `invfn'(`matrixout'[`r', 5]) mat `matrixout'[`r', 6] = `invfn'(`matrixout'[`r', 6]) } } local catrownames = "" if "`mcbnetwork'`pcbnetwork'" != "" { local rownamesmaxlen : strlen local Index local rownamesmaxlen = max(`rownamesmaxlen', 10) } else { local rownamesmaxlen = 10 /*Default*/ } //# equations local init 0 local rnames = "`byrnames' `rnames'" //attach the bynames //Except the grand rows forvalues r = 1(1)`=`byncatreg' + `ncatreg' - `="`grand'"!=""'' { //Labels local rname`r':word `r' of `rnames' tokenize `rname`r'', parse("#") local left = "`1'" local right = "`3'" tokenize `left', parse(.) local leftv = "`3'" local leftlabel = "`1'" //no Interaction if "`right'" == "" { if "`leftv'" != "" { if strpos("`leftlabel'", "o") != 0 { local indexo = strlen("`leftlabel'") - 1 local leftlabel = substr("`leftlabel'", 1, `indexo') } if strpos("`rname`r''", "b") != 0 { local leftlabel = ustrregexra("`leftlabel'", "bn", "") } local lab:label `leftv' `leftlabel' local eqlab "`leftv'" } else { local lab "`leftlabel'" local eqlab "" } local nlencovl : strlen local llab local nlencov = `nlencovl' + 1 } else { //Interaction tokenize `right', parse(.) local rightv = "`3'" local rightlabel = "`1'" if strpos("`leftlabel'", "c") == 0 { if strpos("`leftlabel'", "o") != 0 { local indexo = strlen("`leftlabel'") - 1 local leftlabel = substr("`leftlabel'", 1, `indexo') } if strpos("`leftlabel'", "b") != 0 { local leftlabel = ustrregexra("`leftlabel'", "bn", "") } local llab:label `leftv' `leftlabel' } else { local llab } if strpos("`rightlabel'", "c") == 0 { if strpos("`rightlabel'", "o") != 0 { local indexo = strlen("`rightlabel'") - 1 local rightlabel = substr("`rightlabel'", 1, `indexo') } if strpos("`rightlabel'", "b") != 0 { local rightlabel = ustrregexra("`rightlabel'", "bn", "") } local rlab:label `rightv' `rightlabel' } else { local rlab } if (("`rlab'" != "") + ("`llab'" != "")) == 0 { local lab = "`leftv'#`rightv'" local eqlab = "" } if (("`rlab'" != "") + ("`llab'" != "")) == 1 { local lab = "`llab'`rlab'" local eqlab = "`leftv'*`rightv'" } if (("`rlab'" != "") + ("`llab'" != "")) == 2 { local lab = "`llab'|`rlab'" local eqlab = "`leftv'*`rightv'" } local nlencovl : strlen local leftv local nlencovr : strlen local rightv local nlencov = `nlencovl' + `nlencovr' + 1 } ////check no underscore in the group names, replace with - if strpos("`lab'", "_") != 0 { local lab = ustrregexra("`lab'", "_", "-") } local lab = ustrregexra("`lab'", " ", "_") local nlenlab : strlen local lab if "`eqlab'" != "" { local nlencov = `nlencov' } else { local nlencov = 0 } local rownamesmaxlen = max(`rownamesmaxlen', min(`=`nlenlab' + `nlencov' + 1', 32)) /*Check if there is a longer name*/ local catrownames = "`catrownames' `eqlab':`lab'" } local rownames = "`contrownames' `catrownames' `Overall'" mat rownames `matrixout' = `rownames' if "`expit'" == "" { if "`cimethod'" == "t" { mat colnames `matrixout' = Mean SE t P>|t| Lower Upper } else { mat colnames `matrixout' = Mean SE z P>|z| Lower Upper } } else { if "`cimethod'"== "t" { mat colnames `matrixout' = Mean SE(logit) t(logit) P>|t| Lower Upper } else{ mat colnames `matrixout' = Mean SE(logit) z(logit) P>|z| Lower Upper } } if "`expit'" != "" { mat colnames `outmatrixp' = Lower Upper mat rownames `outmatrixp' = `catrownames' `Overall' } return matrix outmatrixp = `outmatrixp' return matrix outmatrix = `matrixout' end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: postsim +++++++++++++++++++++++++ Simulate & summarize posterior distribution +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop postsim program define postsim, rclass version 14.1 #delimit ; syntax [if] [in], todo(string) orderid(varname) studyid(varname) estimates(name) [ logodds(name) rrout(name) orout(name) link(string) modeles(varname) modellci(varname) modeluci(varname) outplot(string) baselevel(integer 1) cov(string) model(string) comparative by(varname) level(real 95) interaction abnetwork mcbnetwork varx(varname) nsims(string)] ; #delimit cr marksample touse, strok tempname betacoef rawcoef varrawcoef /// fullrawcoef fullvarrawcoef X beta sims /// popabsout popabsouti poprrout poprrouti /// poporout poporouti poplorout poplorouti simvar tempvar feff sfeff reff sreff reff1 sreff1 reff2 sreff2 eta insample /// newobs idpair gid rid hold holdleft holdright /// simmu sumphat meanphat subset subsetid subsetid1 sumphat1 /// meanphat1 gid1 modelp modelrr modelor modellor modelse sumrrhat /// meanrrhat sumorhat meanorhat sumlorhat meanlorhat varint varslope fisherrho /// simvarint simvarslope simfisherrho simrho covar simcovar if "`link'" == "cloglog" { local invfn "invcloglog" } else if "`link'" == "loglog" { local invfn "1-invcloglog" } else { local invfn "invlogit" } //Restore qui { estimates restore `estimates' local predcmd = e(predict) gen `insample' = e(sample) //Coefficients estimates and varcov mat `fullrawcoef' = e(b) mat `fullvarrawcoef' = e(V) local ncoef = colsof(`fullrawcoef') local rho = 0 if "`model'" == "random" { if "`abnetwork'`cov'" == "" { local nfeff = `=`ncoef' - 1' local varnames "`varint'" local simvarnames "`simvarint'" } else if ("`abnetwork'" != "") | ("`cov'" =="independent") { local nfeff = `=`ncoef' - 2' local varnames "`varslope' `varint'" local simvarnames "`simvarslope' `simvarint'" } else if "`cov'" =="unstructured" { local nfeff = `=`ncoef' - 3' if "`predcmd'" == "meqrlogit_p" { local rho = tanh(`fullrawcoef'[1, `ncoef']) local varnames "`varslope' `varint' `fisherrho'" local simvarnames "`simvarslope' `simvarint' `simfisherrho'" } else { local rho = `fullrawcoef'[1, `ncoef']/(sqrt(`fullrawcoef'[1, `=`ncoef'-1']*`fullrawcoef'[1, `=`ncoef'-2'])) local varnames "`varslope' `varint' `covar'" local simvarnames "`simvarslope' `simvarint' `simcovar'" } } } else { local nfeff = `ncoef' } //Get the FE parameters and their covariances mat `betacoef' = `fullrawcoef'[1, 1..`nfeff'] /*if ("`predcmd'" == "meqrlogit_p" & "`model'" == "random" ) | "`model'" != "random" { mat `rawcoef' = `fullrawcoef'[1, 1..`nfeff'] mat `varrawcoef' = `fullvarrawcoef' } else { //Remove the constant's row & column mat `bcoef' = `fullrawcoef'[1, 1..`=`nfeff'-1'] mat `vcoef' = `fullrawcoef'[1, `=`nfeff' + 1'..`ncoef'] mat `rawcoef' = (`bcoef', `vcoef') mat `vcovbcoef' = `fullvarrawcoef'[1..`=`nfeff' - 1', 1..`=`nfeff' - 1'] mat `covbvcoef' = `fullvarrawcoef'[1..`=`nfeff' - 1', `=`nfeff' + 1'..`ncoef'] mat `vcovvcoef' = `fullvarrawcoef'[`=`nfeff' + 1'..`ncoef', `=`nfeff' + 1'..`ncoef'] mat `varrawcoef' = (`vcovbcoef', `covbvcoef' \ `covbvcoef'' , `vcovvcoef') local --nfeff local --ncoef }*/ //Predict //Fill data if less than 7 count local nobs = r(N) if ((`nobs' < 7) & ("`model'" == "random")) { local multipler = int(ceil(7/`nobs')) qui expand `multipler', gen(`newobs') } predict `feff', xb //FE predict `sfeff', stdp //se of FE if "`model'" == "random" { if "`abnetwork'`cov'" == "" { predict `reff', reffects reses(`sreff') gen `eta' = `feff' + `reff' //linear predictor gen `modelse' = sqrt(`sreff'^2 + `sfeff'^2) if `insample'==1 } else if "`abnetwork'" !="" | "`cov'" !="" { predict `reff1' `reff2', reffects reses(`sreff1' `sreff2') //slope=1 int=2 *replace `sreff1' = sqrt((1 - (`rho')^2)*(`sreff1'^2)) //Corrected variance *replace `sreff2' = sqrt((1 - (`rho')^2)*(`sreff2'^2)) //Corrected variance *gen `reff' = `reff1' + `reff1'*(`varx'==2) + `reff2' if "`abnetwork'" == "" { gen `reff' = `reff1'*`varx' + `reff2' gen `sreff' = sqrt(`varx'^2 * `sreff1'^2 + `sreff2'^2) } else { gen `reff' = `reff1' + `reff2' gen `sreff' = sqrt(`sreff1'^2 + `sreff2'^2) } gen `eta' = `feff' + `reff' //linear predictor gen `modelse' = sqrt(`sreff1'^2 + `sreff2'^2 + `sfeff'^2) if `insample'==1 } } else { gen `eta' = `feff' gen `modelse' = `sfeff' if `insample'==1 } //Revert to original data if filler data was generated if (("`model'" == "random") & (`nobs' < 7)) { keep if !`newobs' } //Smooth p estimates gen `modelp' = `invfn'(`eta') if `insample'==1 //identifiers sort `insample' `orderid' *egen `rid' = seq() if `insample'==1 //rowid if "`comparative'`mcbnetwork'`abnetwork'" != "" { egen `gid' = group(`studyid' `by') if `insample'==1 sort `gid' `orderid' `varx' by `gid': egen `idpair' = seq() egen `rid' = seq() if `insample'==1 //rowid if "`abnetwork'" == "" { gen `modelrr' = `modelp'[_n] / `modelp'[_n-1] if (`gid'[_n]==`gid'[_n-1]) & (`idpair' == 2) gen `modelor' = (`modelp'[_n]/(1 - `modelp'[_n])) / (`modelp'[_n-1]/(1 - `modelp'[_n-1])) if (`gid'[_n]==`gid'[_n-1]) & (`idpair' == 2) gen `modellor' = ln(`modelor') } } else { egen `rid' = seq() if `insample'==1 //rowid gen `gid' = `rid' } //Generate designmatrix local colnames :colnames `betacoef' local nvars: word count `colnames' forvalues i=1(1)`nvars' { tempvar v`i' beta`i' local var`i' : word `i' of `colnames' //Interaction tokenize `var`i'', parse("#") local left = "`1'" local right = "`3'" tokenize `left', parse(.) local leftleft = "`1'" local leftright = "`3'" //Constant or continous if "`right'" == "" & "`leftright'" == "" { cap confirm var `leftleft' if _rc!=0 { gen `v`i'' = 0 } else { gen `v`i'' = `leftleft' } } //Main categorical effects if "`right'" == "" & "`leftright'" != "" { if strpos("`leftleft'", "bn") != 0 { local leftleft = ustrregexra("`leftleft'", "bn", "") } if strpos("`leftleft'", "b") != 0 { local leftleft = ustrregexra("`leftleft'", "b", "") } gen `v`i'' = 0 replace `v`i'' = 1 if `leftright' == `leftleft' } //Interactions if "`right'" != "" { tokenize `right', parse(.) local rightleft = "`1'" local rightright = "`3'" //continous left if strpos("`leftleft'", "c") == 1 { local factorleft 0 } else { local factorleft 1 } //continous right if strpos("`rightleft'", "c") == 1 { local factorright 0 } else { local factorright 1 } if `factorleft' == 1 { //Categorical if strpos("`leftleft'", "bn") != 0 { local leftleft = ustrregexra("`leftleft'", "bn", "") } if strpos("`leftleft'", "b") != 0 { local leftleft = ustrregexra("`leftleft'", "b", "") } if strpos("`leftleft'", "o") != 0 { local leftleft = ustrregexra("`leftleft'", "o", "") } if `factorright' == 1 { if strpos("`rightleft'", "bn") != 0 { local rightleft = ustrregexra("`rightleft'", "bn", "") } if strpos("`rightleft'", "b") != 0 { local rightleft = ustrregexra("`rightleft'", "b", "") } if strpos("`rightleft'", "o") != 0 { local rightleft = ustrregexra("`rightleft'", "o", "") } gen `v`i'' = 0 replace `v`i'' = 1 if (`leftright' == `leftleft') & (`rightright' == `rightleft') } else { gen `v`i'' = 0 replace `v`i'' = 1*`rightright' if (`leftright' == `leftleft') } } else { //Continous if `factorright' == 1 { if strpos("`rightleft'", "bn") != 0 { local rightleft = ustrregexra("`rightleft'", "bn", "") } if strpos("`rightleft'", "b") != 0 { local rightleft = ustrregexra("`rightleft'", "b", "") } gen `v`i'' = 0 replace `v`i'' = 1*`leftright' if (`rightright' == `rightleft') } else { gen `v`i'' = . replace `v`i'' = `leftright'*`rightright' } } } local vnamelist "`vnamelist' `v`i''" local bnamelist "`bnamelist' `beta`i''" } if "`model'" == "random" { //Add varnames local bnamelist "`bnamelist' `varnames'" } set matsize `nsims' //make matrices from the dataset //roweq(`idpair') mkmat `vnamelist' if `insample'==1, matrix(`X') rownames(`rid') tempvar present gen `present' = 1 //Simulate the parameters if `nobs' < `nsims' { set obs `nsims' } *drawnorm `bnamelist', n(`nsims') cov(`varrawcoef') means(`rawcoef') seed(1) drawnorm `bnamelist', n(`nsims') cov(`fullvarrawcoef') means(`fullrawcoef') seed(1) *drawnorm `bnamelist', n(`nsims') cov(`varrawcoef') means(`rawcoef') seed(1) forcepsd mkmat `bnamelist', matrix(`beta') //Subset the matrix if `ncoef' > `nfeff' { mat `simvar' = `beta'[1..`nsims', `=`nfeff'+1'..`ncoef'] mat `beta' = `beta'[1..`nsims', 1..`nfeff'] } mat `sims' = `beta'*`X'' //Construct the names local ncols = colsof(`sims') //length of the vector local cnames :colnames `sims' local matcolnames forvalues c=1(1)`ncols' { local matrid : word `c' of `cnames' tempvar festudy`matrid' local matcolnames = "`matcolnames' `festudy`matrid''" } if "`model'" == "random" { //Append the var matrix mat `sims' = (`sims', `simvar') //Add varnames local matcolnames "`matcolnames' `simvarnames'" } //pass the names matname `sims' `matcolnames', col(.) explicit //Bring the matrix to the dataset svmat `sims', names(col) if "`abnetwork'" !="" | "`cov'" !="" { if "`cov'" !="unstructured" { gen `simrho' = 0 } else { if "`predcmd'" == "meqrlogit_p" { gen `simrho' = tanh(`simfisherrho') replace `sreff1' = exp(`simvarslope') //Marginal se replace `sreff2' = sqrt((1 - (`simrho')^2)*(exp(`simvarint')^2)) //Conditional se } else { //Truncate the values to zero replace `simvarslope' = 0 if `simvarslope' < 0 replace `simvarint' = 0 if `simvarint' < 0 replace `simcovar' = 0 if `simvarslope' == 0 & `simvarint' == 0 gen `simrho' = `simcovar'/sqrt(`simvarint'*`simvarslope') replace `sreff1' = sqrt(`simvarslope') //Marginal se replace `sreff2' = sqrt((1 - (`simrho')^2)*(`simvarint')) //Conditional se } } if "`predcmd'" == "meqrlogit_p" { replace `sreff1' = exp(`simvarslope') //Marginal se replace `sreff2' = sqrt((1 - (`simrho')^2)*(exp(`simvarint')^2)) //Conditional se } else { replace `sreff1' = sqrt(`simvarslope') //Marginal se replace `sreff2' = sqrt((1 - (`simrho')^2)*(`simvarint')) //Conditional se } } //# of obs count if `insample' == 1 local nobs = r(N) //Generate the p's and r's forvalues j=1(1)`nobs' { tempvar phat`j' if "`comparative'`mcbnetwork'`abnetwork'" == "" { tempvar restudy`j' phat`j' if "`model'" == "random" { //EB re sum `reff' if `rid' == `j' local reff_`j' = r(mean) //re *sum `reff' if `rid'==`j' *local reff`j' = r(mean) //se *sum `sreff' if `rid'==`j' *local sreff`j' = r(mean) /* if "`predcmd'" == "meqrlogit_p" { qui gen `restudy`j'' = rnormal(0, exp(`simvarint')) } else { qui gen `restudy`j'' = rnormal(0, sqrt(`simvarint')) } *qui gen `restudy`j'' = rnormal(`reff`j'', `sreff`j'') gen `phat`j'' = `invfn'(`restudy`j'' + `festudy`j'') */ if "`predcmd'" == "meqrlogit_p" { qui gen `restudy`j'' = rnormal(0, exp(`simvarint')) } else { qui gen `restudy`j'' = rnormal(0, sqrt(`simvarint')) } gen `phat`j'' = `invfn'(`reff_`j'' + `restudy`j'' + `festudy`j'') } else { gen `phat`j'' = `invfn'(`festudy`j'') } } if "`comparative'" != "" | "`mcbnetwork'" != "" | "`abnetwork'" != "" { sum `gid' if `rid' == `j' local index = r(min) sum `idpair' if `rid' == `j' local pair = r(min) //Generate the variables tempvar phat_`pair'`index' if "`model'" == "random" { //EB re sum `reff' if `rid' == `j' local reff_`j' = r(mean) if `pair' == 1 { //re - same per study *sum `reff' if `gid'==`index' *local reff`j' = r(mean) //se *sum `sreff' if `gid'==`index' *local sreff`j' = r(mean) tempvar restudy`index' if "`abnetwork'`cov'" == "" { if "`predcmd'" == "meqrlogit_p" { gen `restudy`index'' = rnormal(0, exp(`simvarint')) } else { gen `restudy`index'' = rnormal(0, sqrt(`simvarint')) } } else if "`abnetwork'" !="" | "`cov'" !="" { replace `reff1' = rnormal(0, `sreff1') replace `reff2' = rnormal(`simrho'*`sreff2'*(`reff1'/`sreff1'), `sreff2') gen `restudy`index'' = `reff1' + `reff2' *gen `restudy`index'' = rnormal(0, `sreff1') + rnormal(0, `sreff2') } *gen `restudy`index'' = rnormal(`reff`j'', `sreff`j'') } *gen `phat`j'' = `invfn'(`restudy`index'' + `festudy`j'') gen `phat`j'' = `invfn'(`reff_`j'' + `restudy`index'' + `festudy`j'') *gen `phat`j'' = `invfn'(`reff`j'' + `festudy`j'') } else { gen `phat`j'' = `invfn'(`festudy`j'') } if "`abnetwork'" == "" { //Create the pairs gen `phat_`pair'`index'' = `phat`j'' if `pair' == 2 { tempvar rrhat`index' orhat`index' lorhat`index' gen `rrhat`index'' = `phat_2`index'' / `phat_1`index'' gen `orhat`index'' = (`phat_2`index''/(1 - `phat_2`index'')) / (`phat_1`index'' /(1 - `phat_1`index'')) gen `lorhat`index'' = ln(`orhat`index'') } } } } if "`todo'" == "p" { //Summarize p local nrows = rowsof(`logodds') //length of the vector local rnames :rownames `logodds' local eqnames :roweq `logodds' local newnrows = 0 local mindex = 0 foreach vari of local eqnames { local ++mindex local group : word `mindex' of `rnames' //Skip if continous variable if (strpos("`vari'", "_") == 1) & ("`group'" != "Overall"){ continue } cap drop `subset' `subsetid' if "`group'" != "Overall" { if strpos("`vari'", "*") == 0 { *if "`interaction'" == "" { cap drop `hold' decode `vari', gen(`hold') cap drop `subset' local latentgroup = ustrregexra("`group'", "_", " ") gen `subset' = 1 if `hold' == "`latentgroup'" & `insample' == 1 } else { tokenize `vari', parse("*") local leftvar = "`1'" local rightvar = "`3'" tokenize `group', parse("|") local leftgroup = "`1'" local rightgroup = "`3'" cap drop `holdleft' `holdright' decode `leftvar', gen(`holdleft') decode `rightvar', gen(`holdright') cap drop `subset' local latentleftgroup = ustrregexra("`leftgroup'", "_", " ") local latentrightgroup = ustrregexra("`rightgroup'", "_", " ") gen `subset' = 1 if (`holdleft' == "`latentleftgroup'") & (`holdright' == "`latentrightgroup'") & (`insample' == 1) } *egen `subsetid' = group(`rid') if `subset' == 1 egen `subsetid' = seq() if `subset' == 1 } else { //All gen `subset' = 1 if `insample' == 1 gen `subsetid' = `rid' } count if `subset' == 1 local nsubset = r(N) //Compute mean of simulated values cap drop `sumphat' `meanphat' gen `sumphat' = 0 forvalues j=1(1)`nsubset' { sum `rid' if `subsetid' == `j' local index = r(min) replace `sumphat' = `sumphat' + `phat`index'' } //Obtain mean of modelled estimates sum `modelp' if `subset' == 1 local meanmodelp = r(mean) gen `meanphat' = `sumphat'/`nsubset' //Standard error sum `meanphat' local postse = r(sd) //Obtain the quantiles centile `meanphat', centile(50 `=(100-`level')/2' `=100 - (100-`level')/2') local median = r(c_1) //Median local lowerp = r(c_2) //Lower centile local upperp = r(c_3) //Upper centile mat `popabsouti' = (`meanmodelp', `postse', `median', `lowerp', `upperp') mat rownames `popabsouti' = `vari':`group' //Stack the matrices local ++newnrows if `newnrows' == 1 { mat `popabsout' = `popabsouti' } else { mat `popabsout' = `popabsout' \ `popabsouti' } } } if "`todo'" == "r" { //Summarize RR local nrows = rowsof(`rrout') //length of the vector local rnames :rownames `rrout' local eqnames :roweq `rrout' local newnrows 0 if "`comparative'`mcbnetwork'" == "" { local catvars : list uniq eqnames foreach vari of local catvars { cap drop `hold' decode `vari', gen(`hold') label list `vari' local ngroups = r(max) local baselab:label `vari' `baselevel' //count in basegroup tempvar meanphat`baselevel' meanrrhat`baselevel' meanorhat`baselevel' meanlorhat`baselevel' gid`baselevel' sumphat`baselevel' subsetid`baselevel' tempname poprrouti`baselevel' poporouti`baselevel' poplorouti`baselevel' count if `vari' == `baselevel' & `insample' == 1 local ngroup`baselevel' = r(N) egen `subsetid`baselevel'' = group(`rid') if `vari' == `baselevel' & `insample' == 1 cap drop `sumphat`baselevel'' `meanphat`baselevel'' //basegroup gen `sumphat`baselevel'' = 0 forvalues j=1(1)`ngroup`baselevel'' { sum `rid' if `subsetid`baselevel'' == `j' local index = r(min) qui replace `sumphat`baselevel'' = `sumphat`baselevel'' + `phat`index'' } gen `meanphat`baselevel'' = `sumphat`baselevel''/`ngroup`baselevel'' sum `modelp' if `vari' == `baselevel' & `insample' == 1 local meanmodelp`baselevel' = r(mean) mat `poprrouti`baselevel'' = (1, 0, 1, 1, 1) mat `poporouti`baselevel'' = (1, 0, 1, 1, 1) mat `poplorouti`baselevel'' = (1, 0, 1, 1, 1) local baselab = ustrregexra("`baselab'", " ", "_") mat rownames `poprrouti`baselevel'' = `vari':`baselab' mat rownames `poporouti`baselevel'' = `vari':`baselab' mat rownames `poplorouti`baselevel'' = `vari':`baselab' //Other groups forvalues g=1(1)`ngroups' { if `g' != `baselevel' { tempvar meanphat`g' meanrrhat`g' meanorhat`g' meanlorhat`g' gid`g' sumphat`g' subsetid`g' tempname poprrouti`g' poporouti`g' poplorouti`g' local glab:label `vari' `g' count if `vari' == `g' & `insample' == 1 local ngroup`g' = r(N) egen `subsetid`g'' = group(`rid') if `vari' == `g' & `insample' == 1 gen `sumphat`g'' = 0 //Group of interest forvalues j=1(1)`ngroup`g'' { sum `rid' if `subsetid`g'' == `j' local index = r(min) qui replace `sumphat`g'' = `sumphat`g'' + `phat`index'' } gen `meanphat`g'' = `sumphat`g''/`ngroup`g'' //Generate R gen `meanrrhat`g'' = `meanphat`g'' / `meanphat`baselevel'' gen `meanorhat`g'' = (`meanphat`g''/(1 - `meanphat`g'')) / (`meanphat`baselevel''/(1 - `meanphat`baselevel'')) gen `meanlorhat`g'' = ln(`meanorhat`g'') //Obtain mean of modelled estimates sum `modelp' if `vari' == `g' & `insample' == 1 local meanmodelp`g' = r(mean) local meanmodelrr`g' = `meanmodelp`g'' / `meanmodelp`baselevel'' local meanmodelor`g' = (`meanmodelp`g''/(1 - `meanmodelp`g'')) / (`meanmodelp`baselevel''/(1 - `meanmodelp`baselevel'')) local meanmodellor`g' = ln((`meanmodelp`g''/(1 - `meanmodelp`g'')) / (`meanmodelp`baselevel''/(1 - `meanmodelp`baselevel''))) //Standard error sum `meanrrhat`g'' local postserr = r(sd) sum `meanorhat`g'' local postseor = r(sd) sum `meanlorhat`g'' local postselor = r(sd) //Obtain the quantiles centile `meanrrhat`g'', centile(50 `=(100-`level')/2' `=100 - (100-`level')/2') local medianrr = r(c_1) //Median local lowerprr = r(c_2) //Lower centile local upperprr = r(c_3) //Upper centile centile `meanorhat`g'', centile(50 `=(100-`level')/2' `=100 - (100-`level')/2') local medianor = r(c_1) //Median local lowerpor = r(c_2) //Lower centile local upperpor = r(c_3) //Upper centile centile `meanlorhat`g'', centile(50 `=(100-`level')/2' `=100 - (100-`level')/2') local medianlor = r(c_1) //Median local lowerplor = r(c_2) //Lower centile local upperplor = r(c_3) //Upper centile mat `poprrouti`g'' = (`meanmodelrr`g'', `postserr', `medianrr', `lowerprr', `upperprr') mat `poporouti`g'' = (`meanmodelor`g'', `postseor', `medianor', `lowerpor', `upperpor') mat `poplorouti`g'' = (`meanmodellor`g'', `postselor', `medianlor', `lowerplor', `upperplor') local glab = ustrregexra("`glab'", " ", "_") mat rownames `poprrouti`g'' = `vari':`glab' mat rownames `poporouti`g'' = `vari':`glab' mat rownames `poplorouti`g'' = `vari':`glab' } if `g' == 1 { mat `poprrouti' = `poprrouti`g'' mat `poporouti' = `poporouti`g'' mat `poplorouti' = `poplorouti`g'' } else { //Stack the matrices mat `poprrouti' = `poprrouti' \ `poprrouti`g'' mat `poporouti' = `poporouti' \ `poporouti`g'' mat `poplorouti' = `poplorouti' \ `poplorouti`g'' } } //Stack the matrices local ++newnrows if `newnrows' == 1 { mat `poprrout' = `poprrouti' mat `poporout' = `poporouti' mat `poplorout' = `poplorouti' } else { mat `poprrout' = `poprrout' \ `poprrouti' mat `poporout' = `poporout' \ `poporouti' mat `poplorout' = `poplorout' \ `poplorouti' } } } if "`comparative'" != "" | "`mcbnetwork'" != "" { //Comparative R local mindex 0 local newnrows 0 foreach vari of local eqnames { local ++mindex local group : word `mindex' of `rnames' cap drop `subset' if "`group'" != "Overall" { cap drop `hold' decode `vari', gen(`hold') local latentgroup = ustrregexra("`group'", "_", " ") gen `subset' = 1 if `hold' == "`latentgroup'" & `insample' == 1 } else { //All gen `subset' = 1 if `insample' == 1 } cap drop `subsetid' egen `subsetid' = seq() if `subset' == 1 count if `subset' == 1 & `idpair' == 2 local nsubset = r(N) //Compute mean of simulated values cap drop `sumrrhat' `sumorhat' `sumlorhat' gen `sumrrhat' = 0 gen `sumorhat' = 0 gen `sumlorhat' = 0 forvalues j=1(1)`nobs' { sum `gid' if `subsetid' == `j' local index = r(min) sum `idpair' if `subsetid' == `j' local pair = r(min) if `pair' == 2 { qui replace `sumrrhat' = `sumrrhat' + `rrhat`index'' qui replace `sumorhat' = `sumorhat' + `orhat`index'' qui replace `sumlorhat' = `sumlorhat' + `lorhat`index'' } } //Obtain mean of modelled estimates sum `modelrr' if `subset' == 1 local meanmodelrr = r(mean) sum `modelor' if `subset' == 1 local meanmodelor = r(mean) sum `modellor' if `subset' == 1 local meanmodellor = r(mean) cap drop `meanrrhat' `meanorhat' `meanlorhat' gen `meanrrhat' = `sumrrhat'/`nsubset' gen `meanorhat' = `sumorhat'/`nsubset' gen `meanlorhat' = `sumlorhat'/`nsubset' //Standard error sum `meanrrhat' local postserr = r(sd) sum `meanorhat' local postseor = r(sd) sum `meanlorhat' local postselor = r(sd) //Obtain the quantiles centile `meanrrhat' , centile(50 `=(100-`level')/2' `=100 - (100-`level')/2') local medianrr = r(c_1) //Median local lowerprr = r(c_2) //Lower centile local upperprr = r(c_3) //Upper centile centile `meanorhat' , centile(50 `=(100-`level')/2' `=100 - (100-`level')/2') local medianor = r(c_1) //Median local lowerpor = r(c_2) //Lower centile local upperpor = r(c_3) //Upper centile centile `meanlorhat' , centile(50 `=(100-`level')/2' `=100 - (100-`level')/2') local medianlor = r(c_1) //Median local lowerplor = r(c_2) //Lower centile local upperplor = r(c_3) //Upper centile mat `poprrouti' = (`meanmodelrr', `postserr', `medianrr', `lowerprr', `upperprr') mat `poporouti' = (`meanmodelor', `postseor', `medianor', `lowerpor', `upperpor') mat `poplorouti' = (`meanmodellor', `postselor', `medianlor', `lowerplor', `upperplor') mat rownames `poprrouti' = `vari':`group' mat rownames `poporouti' = `vari':`group' mat rownames `poplorouti' = `vari':`group' //Stack the matrices local ++newnrows if `newnrows' == 1 { mat `poprrout' = `poprrouti' mat `poporout' = `poporouti' mat `poplorout' = `poplorouti' } else { mat `poprrout' = `poprrout' \ `poprrouti' mat `poporout' = `poporout' \ `poporouti' mat `poplorout' = `poplorout' \ `poplorouti' } } } } if "`todo'" == "smooth" { replace `modeles' = `modelp' if `insample' == 1 //Smooth p's if "`outplot'" == "abs" { //postci local critvalue -invnorm((100-`level')/200) if "`link'" == "loglog" { local sign - } replace `modellci' = `invfn'(`eta' - `sign' `critvalue'*`modelse') if `insample' == 1 //lower replace `modeluci' = `invfn'(`eta' + `sign' `critvalue'*`modelse') if `insample' == 1 //upper } //Smooth r's if "`outplot'" == "rr" | "`outplot'" == "or" { if "`outplot'" == "rr" { replace `modeles' = `modelrr' if `insample' == 1 } else { replace `modeles' = `modelor' if `insample' == 1 } *sum `gid' if `insample' == 1 count if `insample' == 1 & `idpair' == 2 local nstudies = r(N) egen `subsetid' = seq() if `insample' == 1 & `idpair' == 2 forvalues j=1(1)`nstudies' { sum `gid' if `subsetid' == `j' local index = r(min) //Obtain the quantiles if "`outplot'" == "rr" { centile `rrhat`index'', centile(50 `=(100-`level')/2' `=100 - (100-`level')/2') } else { centile `orhat`index'', centile(50 `=(100-`level')/2' `=100 - (100-`level')/2') } local median = r(c_1) //Median local lowerp = r(c_2) //Lower centile local upperp = r(c_3) //Upper centile replace `modellci' = `lowerp' if (`gid' == `index') & (`idpair' == 2) & `insample' == 1 replace `modeluci' = `upperp' if (`gid' == `index') & (`idpair' == 2) & `insample' == 1 } } } drop if `present' != 1 } //Return matrices if "`todo'" =="p" { mat colnames `popabsout' = Mean SE Median Lower Upper return matrix outmatrix = `popabsout' } if "`todo'" == "r" { mat colnames `poprrout' = Mean SE Median Lower Upper mat colnames `poporout' = Mean SE Median Lower Upper mat colnames `poplorout' = Mean SE Median Lower Upper return matrix rroutmatrix = `poprrout' return matrix oroutmatrix = `poporout' return matrix loroutmatrix = `poplorout' } end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: PRINTMAT +++++++++++++++++++++++++ Print the outplot matrix beautifully +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop printmat program define printmat version 13.1 syntax, matrixout(name) type(string) [sumstat(string) dp(integer 2) power(integer 0) /// mcbnetwork pcbnetwork abnetwork general comparative continuous p(integer 0) model(string) nsims(integer 1000)] local nrows = rowsof(`matrixout') local ncols = colsof(`matrixout') local rnames : rownames `matrixout' local rspec "--`="&"*`=`nrows' - 1''-" local rownames = "" local rownamesmaxlen = 10 /*Default*/ forvalues r = 1(1)`nrows' { local rname : word `r' of `rnames' local nlen : strlen local rname local rownamesmaxlen = max(`rownamesmaxlen', min(`nlen', 32)) //Check if there is a longer name } local nlensstat : strlen local sumstat local nlensstat = max(10, `nlensstat') if "`type'" == "rre" | "`type'" == "ore" { di as res _n "****************************************************************************************" di as txt _n "Wald-type test for nonlinear hypothesis" if "`type'" == "rre" { di as txt _n "{phang}H0: All (log)RR equal vs. H1: Some (log)RR different {p_end}" } else { di as txt _n "{phang}H0: All (log)OR equal vs. H1: Some (log)OR different {p_end}" } #delimit ; noi matlist `matrixout', rowtitle(Parameter) cspec(& %`rownamesmaxlen's | %8.`=`dp''f & %8.0f & %8.`=`dp''f o2&) rspec(`rspec') underscore nodotz ; #delimit cr } if "`type'" == "popabs" | "`type'" == "poprr" | "`type'" == "popor"{ if "`type'" == "popabs" { local parm "Proportion" } else if "`type'" == "poprr" { local parm "Proportion Ratio" } else if "`type'" == "popor" { local parm "Odds Ratio" } di as res _n "****************************************************************************************" di as res _n "Population-averaged estimates: `parm' " tempname mat2print mat `mat2print' = `matrixout' local nrows = rowsof(`mat2print') forvalues r = 1(1)`nrows' { mat `mat2print'[`r', 1] = `mat2print'[`r', 1]*10^`power' mat `mat2print'[`r', 3] = `mat2print'[`r', 3]*10^`power' mat `mat2print'[`r', 4] = `mat2print'[`r', 4]*10^`power' mat `mat2print'[`r', 5] = `mat2print'[`r', 5]*10^`power' forvalues c = 1(1)5 { local cell = `mat2print'[`r', `c'] if "`cell'" == "." { mat `mat2print'[`r', `c'] == .z } } } #delimit ; noi matlist `mat2print', rowtitle(Parameter) cspec(& %`rownamesmaxlen's | %8.`=`dp''f & %8.`=`dp''f & %8.`=`dp''f & %8.`=`dp''f & %8.`=`dp''f o2&) rspec(`rspec') underscore nodotz ; #delimit cr } if ("`type'" == "logit") | ("`type'" == "abs") | ("`type'" == "rr")| ("`type'" == "or") { if ("`model'" == "random") { local typeinf "Conditional" } else { local typeinf "Marginal" } di as res _n "****************************************************************************************" if ("`type'" == "logit") { di as res "{pmore2} `typeinf' Summary: Log odds {p_end}" } if ("`type'" == "abs") { di as res "{pmore2} `typeinf' summary: Proportion {p_end}" } if ("`type'" == "rr") { di as res "{pmore2} `typeinf' summary: Proportion Ratio {p_end}" } if ("`type'" == "or") { di as res "{pmore2} `typeinf' summary: Odds Ratio {p_end}" } di as res "****************************************************************************************" tempname mat2print mat `mat2print' = `matrixout' local nrows = rowsof(`mat2print') forvalues r = 1(1)`nrows' { mat `mat2print'[`r', 1] = `mat2print'[`r', 1]*10^`power' mat `mat2print'[`r', 5] = `mat2print'[`r', 5]*10^`power' mat `mat2print'[`r', 6] = `mat2print'[`r', 6]*10^`power' forvalues c = 1(1)6 { local cell = `mat2print'[`r', `c'] if "`cell'" == "." { mat `mat2print'[`r', `c'] == .z } } } #delimit ; noi matlist `mat2print', rowtitle(Parameter) cspec(& %`rownamesmaxlen's | %`nlensstat'.`=`dp''f & %9.`=`dp''f & %8.`=`dp''f & %15.`=`dp''f & %8.`=`dp''f & %8.`=`dp''f o2&) rspec(`rspec') underscore nodotz ; #delimit cr } if ("`type'" == "het") { di as res _n "****************************************************************************************" di as txt _n "Test of heterogeneity - LR Test: RE model vs FE model" tempname mat2print mat `mat2print' = `matrixout' forvalues r = 1(1)`nrows' { forvalues c = 1(1)`ncols' { local cell = `mat2print'[`r', `c'] if "`cell'" == "." { mat `mat2print'[`r', `c'] == .z } } } #delimit ; noi matlist `mat2print', cspec(& %`rownamesmaxlen's | %8.0f `="& %10.`=`dp''f "*`=`ncols'-1'' o2&) rspec(`rspec') underscore nodotz ; #delimit cr } if ("`type'" == "mc") { di as res _n "****************************************************************************************" di as txt _n "Model comparison(s): Leave-one-out LR Test(s)" local rownamesmaxlen = max(`rownamesmaxlen', 17) //Check if there is a longer name #delimit ; noi matlist `matrixout', rowtitle(Omitted Parameter) cspec(& %`=`rownamesmaxlen' + 2's | %8.`=`dp''f & %8.0f & %8.`=`dp''f & %15.`=`dp''f o2&) rspec(`rspec') underscore nodotz ; #delimit cr if "`interaction'" !="" { di as txt "*NOTE: Model with and without interaction parameter(s)" } else { di as txt "*NOTE: Model with and without main parameter(s)" } di as txt "*NOTE: Delta BIC = BIC (specified model) - BIC (reduced model) " } if ("`continuous'" != "") { di as txt "NOTE: For continuous variable margins are computed at their respective mean" } if ("`type'" == "abs") { di as txt "NOTE: H0: Est = 0.5 vs. H1: Est != 0.5" } if ("`type'" == "rr") { di as txt "NOTE: H0: Est = 1 vs. H1: Est != 1" } if ("`type'" == "logit") { di as txt "NOTE: H0: Est = 0 vs. H1: Est != 0" } if ("`type'" == "popabs") | ("`type'" == "poprr") | ("`type'" == "popor") { di as txt "NOTE: `level'% centiles obtained from `nsims' simulations of the posterior distribution" } if ("`type'" == "logit") { di _n display `"{stata "estimates replay metapreg_modest":Click to show the raw estimates}"' } end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: ESTRCORE +++++++++++++++++++++++++ Obtain the RR after modelling +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop estrcore program define estrcore, rclass version 13.1 syntax, marginlist(string) [cimethod(string) varx(varname) by(varname) confounders(varlist) level(integer 95) /// baselevel(integer 1) estimates(string) link(string)] tempname lRRcoef lRRV RRoutmatrix nltestRR lORcoef lORV ORoutmatrix nltestOR //Expression for logodds prediction if "`link'" == "cloglog" { local expression "exp(logit(invcloglog(predict(xb))))" } else if "`link'" == "loglog" { local expression "exp(-logit(invcloglog(predict(xb))))" } else { local expression "exp(predict(xb))" } //Approximate sampling distribution critical value qui estimates restore `estimates' local df = e(N) - e(k) if "`cimethod'" != "wald" { local critvalue invttail(`df', `=(100-`level')/200') } else { local critvalue -invnorm((100-`level')/200) } local EstRRlnexpression //log RR local EstORlnexpression //log OR foreach c of local confounders { qui label list `c' local nlevels = r(max) local test_`c' if "`varx'" != "" { forvalues l = 1/`nlevels' { if `l' == 1 { local test_`c' = "_b[`c'_`l']" } else { local test_`c' = "_b[`c'_`l'] = `test_`c''" } local EstRRlnexpression = "`EstRRlnexpression' (`c'_`l': ln(invlogit(_b[`l'.`c'#2.`varx'])) - ln(invlogit(_b[`l'.`c'#1.`varx'])))" local EstORlnexpression = "`EstORlnexpression' (`c'_`l': _b[`l'.`c'#2.`varx'] - _b[`l'.`c'#1.`varx'])" } } else { local test_`c' = "_b[`c'_`baselevel']" local init 1 forvalues l = 1/`nlevels' { if `l' != `baselevel' { local test_`c' = "_b[`c'_`l'] = `test_`c''" } local EstRRlnexpression = "`EstRRlnexpression' (`c'_`l': ln(invlogit(_b[`l'.`c'])) - ln(invlogit(_b[`baselevel'.`c'])))" local EstORlnexpression = "`EstORlnexpression' (`c'_`l': _b[`l'.`c'] - _b[`baselevel'.`c'])" } } } //RR qui estimates restore `estimates' qui margins `marginlist', `expression' over(`by') post level(`level') qui nlcom `EstRRlnexpression', post level(`level') mat `lRRcoef' = e(b) mat `lRRV' = e(V) mat `lRRV' = vecdiag(`lRRV') local ncols = colsof(`lRRcoef') //length of the vector local rnames :colnames `lRRcoef' local rowtestnl local i = 1 foreach c of local confounders { qui label list `c' local nlevels = r(max) if (`nlevels' > 2 & "`varx'" == "") | (`nlevels' > 1 & "`varx'" != "" ){ qui testnl (`test_`c'') local testnl_`c'_chi2 = r(chi2) local testnl_`c'_df = r(df) local testnl_`c'_p = r(p) if `i'==1 { mat `nltestRR' = [`testnl_`c'_chi2', `testnl_`c'_df', `testnl_`c'_p'] } else { mat `nltestRR' = `nltestRR' \ [`testnl_`c'_chi2', `testnl_`c'_df', `testnl_`c'_p'] } local ++i local rowtestnl = "`rowtestnl' `c' " } } //OR qui estimates restore `estimates' qui margins `marginlist', `expression' over(`by') post level(`level') qui nlcom `EstORlnexpression', post level(`level') mat `lORcoef' = e(b) mat `lORV' = e(V) mat `lORV' = vecdiag(`lORV') local ncols = colsof(`lORcoef') //length of the vector local rnames :colnames `lORcoef' local i = 1 foreach c of local confounders { qui label list `c' local nlevels = r(max) if (`nlevels' > 2 & "`varx'" == "") | (`nlevels' > 1 & "`varx'" != "" ){ qui testnl (`test_`c'') local testnl_`c'_chi2 = r(chi2) local testnl_`c'_df = r(df) local testnl_`c'_p = r(p) if `i'==1 { mat `nltestOR' = [`testnl_`c'_chi2', `testnl_`c'_df', `testnl_`c'_p'] } else { mat `nltestOR' = `nltestOR' \ [`testnl_`c'_chi2', `testnl_`c'_df', `testnl_`c'_p'] } local ++i } } mat `RRoutmatrix' = J(`ncols', 6, .) mat `ORoutmatrix' = J(`ncols', 6, .) forvalues r = 1(1)`ncols' { mat `RRoutmatrix'[`r', 1] = exp(`lRRcoef'[1,`r']) /*Estimate*/ mat `RRoutmatrix'[`r', 2] = sqrt(`lRRV'[1, `r']) /*se in log scale, power 1*/ mat `RRoutmatrix'[`r', 3] = `lRRcoef'[1,`r']/sqrt(`lRRV'[1, `r']) /*Z in log scale*/ mat `ORoutmatrix'[`r', 1] = exp(`lORcoef'[1,`r']) /*Estimate*/ mat `ORoutmatrix'[`r', 2] = sqrt(`lORV'[1, `r']) /*se in log scale, power 1*/ mat `ORoutmatrix'[`r', 3] = `lORcoef'[1,`r']/sqrt(`lORV'[1, `r']) /*Z in log scale*/ if "`cimethod'" != "wald" { mat `RRoutmatrix'[`r', 4] = ttail(`df', abs(`RRoutmatrix'[`r', 3]))*2 /*p-value*/ mat `ORoutmatrix'[`r', 4] = ttail(`df', abs(`ORoutmatrix'[`r', 3]))*2 /*p-value*/ } else { mat `RRoutmatrix'[`r', 4] = normprob(-abs(`RRoutmatrix'[`r', 3]))*2 /*p-value*/ mat `ORoutmatrix'[`r', 4] = normprob(-abs(`ORoutmatrix'[`r', 3]))*2 /*p-value*/ } mat `RRoutmatrix'[`r', 5] = exp(`lRRcoef'[1, `r'] - `critvalue' * sqrt(`lRRV'[1, `r'])) /*lower*/ mat `RRoutmatrix'[`r', 6] = exp(`lRRcoef'[1, `r'] + `critvalue' * sqrt(`lRRV'[1, `r'])) /*upper*/ mat `ORoutmatrix'[`r', 5] = exp(`lORcoef'[1, `r'] - `critvalue' * sqrt(`lORV'[1, `r'])) /*lower*/ mat `ORoutmatrix'[`r', 6] = exp(`lORcoef'[1, `r'] + `critvalue' * sqrt(`lORV'[1, `r'])) /*upper*/ } local rownames = "" local rownamesmaxlen = 10 /*Default*/ local nrows = rowsof(`RRoutmatrix') forvalues r = 1(1)`nrows' { local rname`r':word `r' of `rnames' tokenize `rname`r'', parse("_") local left = "`1'" local right = "`3'" if "`3'" != "" { local lab:label `left' `right' local lab = ustrregexra("`lab'", " ", "_") local nlen : strlen local lab local rownamesmaxlen = max(`rownamesmaxlen', min(`nlen', 32)) //Check if there is a longer name local rownames = "`rownames' `left':`lab'" } } mat rownames `RRoutmatrix' = `rownames' mat rownames `ORoutmatrix' = `rownames' if `i' > 1 { mat rownames `nltestRR' = `rowtestnl' mat rownames `nltestOR' = `rowtestnl' return matrix nltestRR = `nltestRR' return matrix nltestOR = `nltestOR' } return local i = "`i'" return matrix rroutmatrix = `RRoutmatrix' return matrix oroutmatrix = `ORoutmatrix' end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: ESTR +++++++++++++++++++++++++ Estimate RR after modelling +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop estr program define estr, rclass version 13.1 syntax, estimates(string) studyid(varname) [catreg(varlist) typevarx(string) varx(varname) comparator(varname) cimethod(string) /// level(integer 95) DP(integer 2) mcbnetwork pcbnetwork abnetwork general comparative stratify power(integer 0) by(varname) /// regexpression(string) baselevel(integer 1) interaction link(string)] //Expression for logodds prediction if "`link'" == "cloglog" { local expression "exp(logit(invcloglog(predict(xb))))" } else if "`link'" == "loglog" { local expression "exp(-logit(invcloglog(predict(xb))))" } else { local expression "exp(predict(xb))" } local invfn "invlogit" //Approximate sampling distribution critical value if "`cimethod'" != "wald" { qui estimates restore `estimates' local df = e(N) - e(k) local critvalue invttail(`df', `=(100-`level')/200') } else { local critvalue -invnorm((100-`level')/200) } if "`comparative'`mcbnetwork'`pcbnetwork'" != "" { local idpairconcat "#`varx'" } if "`mcbnetwork'`pcbnetwork'" != "" { tokenize `regexpression' if "`interaction'" != "" { tokenize `2', parse(".") } else { tokenize `3', parse(".") } local index "`3'" if "`by'" ! = "`index'" { local catreg = "`3' `catreg'" } local stratify //nullify } local confounders "`catreg'" *if "`mcbnetwork'`pcbnetwork'" != "" { * local confounders "`by' `catreg'" *} local marginlist while "`catreg'" != "" { tokenize `catreg' local first "`1'" macro shift local catreg `*' if "`first'" != "`studyid'" { local marginlist = `"`marginlist' `first'`idpairconcat'"' } } tempname lRRcoef lRRV RRoutmatrix lORcoef lORV ORoutmatrix row /// outmatrixr overallRR overallOR nltestRR nltestOR rowtestnl testmat2print bymatRR bymatOR /// bynltestRR bynltestOR compmatRR compmatOR compnltestRR /// compnltestOR catregmatRR catregmatOR catregnltestRR catregnltestOR varxcoef local nrowsout 0 local nrowsnl 0 local nby 0 local ncomp 0 local ncatreg 0 if "`by'" != "" & "`typevarx'" == "i" & "`stratify'" == "" { estrcore, marginlist(`varx') varx(`varx') by(`by') confounders(`by') estimates(`estimates') cimethod(`cimethod') link(`link') matrix `bymatRR' = r(rroutmatrix) matrix `bymatOR' = r(oroutmatrix) local nby = rowsof(`bymatRR') local iby = r(i) if `iby' > 1 { matrix `bynltestRR' = r(nltestRR) matrix `bynltestOR' = r(nltestOR) matrix `nltestRR' = `bynltestRR' matrix `nltestOR' = `bynltestOR' local nrowsnl = rowsof(`nltestRR') } mat `RRoutmatrix' = `bymatRR' mat `ORoutmatrix' = `bymatOR' local nrowsout = rowsof(`RRoutmatrix') } qui label list `comparator' local nc = r(max) if ("`by'" != "`comparator'") & ("`comparator'" != "") & (`nc' > 1) { estrcore, marginlist(`varx') varx(`varx') by(`comparator') confounders(`comparator') estimates(`estimates') cimethod(`cimethod') link(`link') matrix `compmatRR' = r(rroutmatrix) matrix `compmatOR' = r(oroutmatrix) local ncomp = rowsof(`compmatRR') local icomp = r(i) if `icomp' > 1 { matrix `compnltestRR' = r(nltestRR) matrix `compnltestOR' = r(nltestOR) if `nrowsnl' > 0 { matrix `nltestRR' = `nltestRR' \ `compnltestRR' matrix `nltestOR' = `nltestOR' \ `compnltestOR' } else { matrix `nltestRR' = `compnltestRR' matrix `nltestOR' = `compnltestOR' } local nrowsnl = rowsof(`nltestRR') } if `nrowsout' > 0 { matrix `RRoutmatrix' = `RRoutmatrix' \ `compmatRR' matrix `ORoutmatrix' = `ORoutmatrix' \ `compmatOR' } else { matrix `RRoutmatrix' = `compmatRR' matrix `ORoutmatrix' = `compmatOR' } local nrowsout = rowsof(`RRoutmatrix') } if "`marginlist'" != "" { if "`comparative'`mcbnetwork'`pcbnetwork'" != "" { estrcore, marginlist(`marginlist') varx(`varx') confounders(`confounders') baselevel(`baselevel') estimates(`estimates') cimethod(`cimethod') link(`link') } else { estrcore, marginlist(`marginlist') confounders(`confounders') baselevel(`baselevel') estimates(`estimates') cimethod(`cimethod') link(`link') } matrix `catregmatRR' = r(rroutmatrix) matrix `catregmatOR' = r(oroutmatrix) local ncatreg = rowsof(`catregmatRR') local icatreg = r(i) if `icatreg' > 1 { matrix `catregnltestRR' = r(nltestRR) matrix `catregnltestOR' = r(nltestOR) if `nrowsnl' > 0 { matrix `nltestRR' = `nltestRR' \ `catregnltestRR' matrix `nltestOR' = `nltestOR' \ `catregnltestOR' } else { matrix `nltestRR' = `catregnltestRR' matrix `nltestOR' = `catregnltestOR' } local nrowsnl = rowsof(`nltestRR') } if `nrowsout' > 0 { matrix `RRoutmatrix' = `RRoutmatrix' \ `catregmatRR' matrix `ORoutmatrix' = `ORoutmatrix' \ `catregmatOR' } else { matrix `RRoutmatrix' = `catregmatRR' matrix `ORoutmatrix' = `catregmatOR' } local nrowsout = rowsof(`RRoutmatrix') } if "`comparative'`mcbnetwork'`pcbnetwork'" != "" { mat `overallRR' = J(1, 6, .) mat `overallOR' = J(1, 6, .) qui estimates restore `estimates' local df = e(N) - e(k) qui margins `varx', `expression' post level(`level') mat `varxcoef' = e(b)' local varxcats:rownames `varxcoef' forvalues r = 1(1)2 { local rname`r':word `r' of `varxcats' tokenize `rname`r'', parse(.) local coef`r' = "`1'" if strpos("`coef`r''", "bn") != 0 { local coef`r' = ustrregexra("`coef`r''", "bn", "") } } //log rr metric qui nlcom (Overall: ln(`invfn'(_b[`coef2'.`varx'])) - ln(`invfn'(_b[`coef1'.`varx']))) mat `lRRcoef' = r(b) mat `lRRV' = r(V) mat `lRRV' = vecdiag(`lRRV') //log or metric qui nlcom (Overall: _b[`coef2'.`varx'] - _b[`coef1'.`varx']) mat `lORcoef' = r(b) mat `lORV' = r(V) mat `lORV' = vecdiag(`lORV') mat `overallRR'[1, 1] = exp(`lRRcoef'[1,1]) //rr mat `overallRR'[1, 2] = sqrt(`lRRV'[1, 1]) //se mat `overallRR'[1, 3] = `lRRcoef'[1, 1]/sqrt(`lRRV'[1, 1]) //zvalue mat `overallOR'[1, 1] = exp(`lORcoef'[1,1]) //or mat `overallOR'[1, 2] = sqrt(`lORV'[1, 1]) //se mat `overallOR'[1, 3] = `lORcoef'[1, 1]/sqrt(`lORV'[1, 1]) //zvalue if "`cimethod'" != "wald" { mat `overallRR'[1, 4] = ttail(`df', -abs(`overallRR'[1, 3]))*2 //pvalue mat `overallOR'[1, 4] = ttail(`df', -abs(`overallOR'[1, 3]))*2 //pvalue } else { mat `overallRR'[1, 4] = normprob(-abs(`overallRR'[1, 3]))*2 //pvalue mat `overallOR'[1, 4] = normprob(-abs(`overallOR'[1, 3]))*2 //pvalue } mat `overallRR'[1, 5] = exp(`lRRcoef'[1, 1] - `critvalue'*sqrt(`lRRV'[1, 1])) //ll mat `overallRR'[1, 6] = exp(`lRRcoef'[1, 1] + `critvalue'*sqrt(`lRRV'[1, 1])) //ul mat `overallOR'[1, 5] = exp(`lORcoef'[1, 1] - `critvalue'*sqrt(`lORV'[1, 1])) //ll mat `overallOR'[1, 6] = exp(`lORcoef'[1, 1] + `critvalue'*sqrt(`lORV'[1, 1])) //ul mat rownames `overallRR' = :Overall mat rownames `overallOR' = :Overall if `nrowsout' > 0 { matrix `RRoutmatrix' = `RRoutmatrix' \ `overallRR' matrix `ORoutmatrix' = `ORoutmatrix' \ `overallOR' } else { matrix `RRoutmatrix' = `overallRR' matrix `ORoutmatrix' = `overallOR' } local nrowsout = rowsof(`RRoutmatrix') } if "`cimethod'" == "wald" { mat colnames `RRoutmatrix' = Mean SE(lrr) z(lrr) P>|z| Lower Upper mat colnames `ORoutmatrix' = Mean SE(lor) z(lor) P>|z| Lower Upper } else { mat colnames `RRoutmatrix' = Mean SE(lrr) t(lrr) P>|t| Lower Upper mat colnames `ORoutmatrix' = Mean SE(lor) t(lor) P>|t| Lower Upper } if `nrowsnl' > 0 { local inltest = "yes" mat colnames `nltestRR' = chi2 df p mat colnames `nltestOR' = chi2 df p return matrix nltestRR = `nltestRR' return matrix nltestOR = `nltestOR' } else { local inltest = "no" } return local inltest = "`inltest'" return matrix rroutmatrix = `RRoutmatrix' return matrix oroutmatrix = `ORoutmatrix' end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: KOOPMANCI +++++++++++++++++++++++++ CI for RR ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop koopmanci program define koopmanci version 14.1 syntax varlist, r(name) lowerci(name) upperci(name) [alpha(real 0.05)] qui { tokenize `varlist' gen `r' = . gen `lowerci' = . gen `upperci' = . tempname matci count forvalues i = 1/`r(N)' { local n1 = `1'[`i'] local N1 = `2'[`i'] local n2 = `3'[`i'] local N2 = `4'[`i'] koopmancii `n1' `N1' `n2' `N2', alpha(`alpha') mat `matci' = r(ci) if (`n1' == 0) &(`n2'==0) { replace `r' = 0 in `i' } else { replace `r' = (`n1'/`N1')/(`n2'/`N2') in `i' } replace `lowerci' = `matci'[1, 1] in `i' replace `upperci' = `matci'[1, 2] in `i' } } end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: KOOPMANCII +++++++++++++++++++++++++ CI for RR ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop koopmancii program define koopmancii, rclass version 14.1 syntax anything(name=data id="data"), [alpha(real 0.05)] local len: word count `data' if `len' != 4 { di as error "Specify full data: n1 N1 n2 N2" exit } foreach num of local data { cap confirm integer number `num' if _rc != 0 { di as error "`num' found where integer expected" exit } } tokenize `data' cap assert ((`1' <= `2') & (`3' <= `4')) if _rc != 0{ di as err "Order should be n1 N1 n2 N2" exit _rc } mata: koopman_ci((`1', `2', `3', `4'), `alpha') return matrix ci = ci return scalar alpha = `alpha' end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: cmlCI +++++++++++++++++++++++++ CI for RR ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop cmlci program define cmlci version 14.1 syntax varlist, r(name) lowerci(name) upperci(name) [alpha(real 0.05)] qui { tokenize `varlist' gen `r' = . gen `lowerci' = . gen `upperci' = . tempname matci count forvalues i = 1/`r(N)' { local a = `1'[`i'] local b = `2'[`i'] local c = `3'[`i'] local d = `4'[`i'] cmlcii `a' `b' `c' `d', alpha(`alpha') mat `matci' = r(ci) local n = `a' + `b' + `c' + `d' local p1 = (`a' + `b')/`n' local p0 = (`a' + `c')/`n' local RR = `p1'/`p0' replace `r' = `RR' in `i' replace `lowerci' = `matci'[1, 1] in `i' replace `upperci' = `matci'[1, 2] in `i' } } end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: cmlCII +++++++++++++++++++++++++ CI for RR ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop cmlcii program define cmlcii, rclass version 14.1 syntax anything(name=data id="data"), [alpha(real 0.05)] local len: word count `data' if `len' != 4 { di as error "Specify full data: a b c d" exit } foreach num of local data { cap confirm integer number `num' if _rc != 0 { di as error "`num' found where integer expected" exit } } tokenize `data' mata: cml_ci((`1', `2', `3', `4'), `alpha') return matrix ci = ci return scalar alpha = `alpha' end /*+++++++++++++++++++++++++ SUPPORTING FUNCTIONS: ORCCCI +++++++++++++++++++++++++ CI for OR ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ cap program drop orccci program define orccci version 14.1 syntax varlist, r(name) lowerci(name) upperci(name) [level(real 95) mcbnetwork cimethod(string)] qui { tokenize `varlist' gen `r' = . gen `lowerci' = . gen `upperci' = . count forvalues i = 1/`r(N)' { if "`mcbnetwork'" != "" { local a = `1'[`i'] local b = `2'[`i'] local c = `3'[`i'] local d = `4'[`i'] cci `=`a'+`b'' `=`c'+`d'' `=`a'+`c'' `=`b' +`d'', l(`level') `cimethod' } else { local n1 = `1'[`i'] local N1 = `2'[`i'] local n2 = `3'[`i'] local N2 = `4'[`i'] cci `n1' `=`N1'-`n1'' `n2' `=`N2'-`n2'', l(`level') `cimethod' } local OR = r(or) local lor = r(lb_or) local uor = r(ub_or) replace `r' = `OR' in `i' replace `lowerci' = `lor' in `i' replace `upperci' = `uor' in `i' } } end /*==================================== GETWIDTH ================================================*/ /*===============================================================================================*/ capture program drop getlen program define getlen version 14.1 //From metaprop qui{ gen `2' = 0 count local N = r(N) forvalues i = 1/`N'{ local this = `1'[`i'] local width: _length "`this'" replace `2' = `width' in `i' } } end /* SUPPORTING FUNCTIONS: FPLOT ++++++++++++++++++++++++++++++++++++++++++++++++ The forest plot +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ // Some re-used code from metaprop, metadta capture program drop fplot program define fplot version 14.1 #delimit ; syntax varlist [if] [in] [, STudyid(varname) POWer(integer 0) DP(integer 2) Level(integer 95) Groupvar(varname) AStext(integer 50) ARRowopt(string) CIOpts(string) DIAMopts(string) DOUble LCols(varlist) RCols(varlist) noOVLine noSTATS noWT noBox OLineopts(string) outplot(string) SUMStat(string asis) POINTopts(string) BOXopts(string) predciopts(string) SUBLine TEXts(real 1.0) XLAbel(string) XLIne(string) XTick(string) GRID GRAphsave(string asis) prediction logscale comparative abnetwork pcbnetwork mcbnetwork general smooth model(string) * ]; #delimit cr local fopts `"`options'"' tempvar es modeles lci modellci uci modeluci lpi upi ilci iuci predid use label tlabel id newid rid gid df expand expanded order orig flag /// tokenize "`varlist'", parse(" ") qui { gen `es' =`1'*(10^`power') gen `lci' =`2'*(10^`power') gen `uci' =`3'*(10^`power') gen byte `use' =`4' gen str `label' =`5' gen `df' = `6' gen `id' = `7' if "`smooth'" !="" { gen `modeles' = `8'*(10^`power') gen `modellci' = `9'*(10^`power') gen `modeluci' = `10'*(10^`power') } //Toggle for comparative if "`comparative'" != "" & "`outplot'" == "abs" { local compabs "compabs" } gen `newid' = `id' //Add five spaces on top of the dataset and 1 space below *qui summ `id' gen `expand' = 1 replace `expand' = 1 + 5*(_n==1) + 1*(_n==_N) expand `expand' sort `newid' `use' replace `newid' = _n in 1/6 replace `newid' = `newid' + 5 if _n>6 replace `label' = "" in 1/5 replace `use' = -2 in 1/4 replace `use' = 0 in 5 replace `newid' = _N if _N==_n replace `use' = 0 if _N==_n replace `label' = "" if _N==_n gen `flag' = 1 replace `flag' = 0 in 1/4 //studylables if "`abnetwork'" != "" & "`outplot'" != "abs" { local studylb: variable label `groupvar' if "`studylb'" == "" { label var `label' "`groupvar'" } else { label var `label' "`studylb'" } } else { local studylb: variable label `studyid' if "`studylb'" == "" { label var `label' "`studyid'" } else { label var `label' "`studylb'" } } *local titleOff = 0 if "`lcols'" == "" { local lcols = "`label'" *local titleOff = 1 } else { local lcols "`label' `lcols'" } if "`compabs'" != "" { replace `id' = `newid' drop `newid' } else{ egen `rid' = group(`newid') replace `id' = `rid' drop `rid' `newid' } tempvar estText index predText predLabel wtText modelestText gen str `estText' = string(`es', "%10.`=`dp''f") + " (" + string(`lci', "%10.`=`dp''f") + ", " + string(`uci', "%10.`=`dp''f") + ")" if (`use' == 1 | `use' == 2 | `use' == 3) if "`smooth'" !="" { gen str `modelestText' = string(`modeles', "%10.`=`dp''f") + " (" + string(`modellci', "%10.`=`dp''f") + ", " + string(`modeluci', "%10.`=`dp''f") + ")" if (`use' == 1 ) replace `modelestText' = string(`es', "%10.`=`dp''f") + " (" + string(`lci', "%10.`=`dp''f") + ", " + string(`uci', "%10.`=`dp''f") + ")" if (`use' == 2 | `use' == 3) replace `estText' = " " if (`use' == 2 | `use' == 3) } if "`wt'" == "" { gen str `wtText' = string(_WT, "%10.`=`dp''f") if (`use' == 1 | `use' == 2 | `use' == 3) } if "`prediction'" != "" { tempvar lenestext replace `estText' = " (" + string(`lci', "%10.`=`dp''f") + ", " + string(`uci', "%10.`=`dp''f") + ")" if (`use' == 4) qui gen `lenestext' = length(`estText') qui summ `lenestext' if `use' == 1 local lentext = r(max) qui summ `lenestext' if `use' == 4 local lenic = r(min) local lenwhite = `lentext' - `lenic' replace `estText' = ". `=`lenwhite'*" "'" + `estText' if (`use' == 4) } // GET MIN AND MAX DISPLAY // SORT OUT TICKS- CODE PINCHED FROM MIKE AND FIRandomED. TURNS OUT I'VE BEEN USING SIMILAR NAMES... // AS SUGGESTED BY JS JUST ACCEPT ANYTHING AS TICKS AND RESPONSIBILITY IS TO USER! if "`logscale'" != "" { replace `es' = ln(`es') replace `lci' = ln(`lci') replace `uci' = ln(`uci') if "`smooth'" !="" { replace `modeles' = ln(`modeles') replace `modellci' = ln(`modellci') replace `modeluci' = ln(`modeluci') } } qui summ `lci', detail local DXmin = r(min) qui summ `uci', detail local DXmax = r(max) if "`xlabel'" != "" { if "`logscale'" != "" { local DXmin = ln(min(`xlabel')) local DXmax = ln(max(`xlabel')) } else{ local DXmin = min(`xlabel') local DXmax = max(`xlabel') } } if "`xlabel'"=="" { local xlabel "0, `DXmax'" } local lblcmd "" tokenize "`xlabel'", parse(",") while "`1'" != ""{ if "`1'" != ","{ local lbl = string(`1',"%7.3g") if "`logscale'" != "" { if "`1'" == "0" { local val = ln(`=10^(-`dp')') } else { local val = ln(`1') } } else { local val = `1' } local lblcmd `lblcmd' `val' "`lbl'" } mac shift } if "`xtick'" == ""{ local xtick = "`xlabel'" } local xtick2 = "" tokenize "`xtick'", parse(",") while "`1'" != ""{ if "`1'" != ","{ if "`logscale'" != "" { if "`1'" == "0" { local val = ln(`=10^(-`dp')') } else { local val = ln(`1') } } else { local val = `1' } local xtick2 = "`xtick2' " + string(`val') } if "`1'" == ","{ local xtick2 = "`xtick2'`1'" } mac shift } local xtick = "`xtick2'" local DXmin = (min(`xtick',`DXmin')) local DXmax = (max(`xtick',`DXmax')) *local DXmin= (min(`xlabel',`xtick',`DXmin')) *local DXmax= (max(`xlabel',`xtick',`DXmax')) local DXwidth = `DXmax'-`DXmin' } // END QUI /*===============================================================================================*/ /*==================================== COLUMNS ================================================*/ /*===============================================================================================*/ qui { // KEEP QUIET UNTIL AFTER DIAMONDS // DOUBLE LINE OPTION if "`double'" != "" & ("`lcols'" != "" | "`rcols'" != ""){ replace `expand' = 1 replace `expand' = 2 if `use' == 1 expand `expand' sort `id' `use' bys `id' : gen `index' = _n sort `id' `use' `index' egen `newid' = group(`id' `index') replace `id' = `newid' drop `newid' replace `use' = 1 if `index' == 2 replace `es' = . if `index' == 2 replace `lci' = . if `index' == 2 replace `uci' = . if `index' == 2 replace `estText' = "" if `index' == 2 foreach var of varlist `lcols' `rcols' { cap confirm string var `var' if _rc == 0 { tempvar length words tosplit splitwhere best gen `splitwhere' = 0 gen `best' = . gen `length' = length(`var') summ `length', det gen `words' = wordcount(`var') gen `tosplit' = 1 if `length' > r(max)/2+1 & `words' >= 2 summ `words', det local max = r(max) forvalues i = 1/`max'{ replace `splitwhere' = strpos(`var', word(`var',`i')) /// if abs( strpos(`var',word(`var',`i')) - length(`var')/2 ) < `best' /// & `tosplit' == 1 replace `best' = abs(strpos(`var',word(`var',`i')) - length(`var')/2) /// if abs(strpos(`var',word(`var',`i')) - length(`var')/2) < `best' } replace `var' = substr(`var',1,(`splitwhere'-1)) if (`tosplit' == 1) & (`index' == 1) replace `var' = substr(`var',`splitwhere',length(`var')) if (`tosplit' == 1) & (`index' == 2) replace `var' = "" if (`tosplit' != 1) & (`index' == 2) & (`use' == 1) drop `length' `words' `tosplit' `splitwhere' `best' } if _rc != 0{ replace `var' = . if (`index' == 2) & (`use' == 1) } } } local maxline = 1 if "`lcols'" != "" { tokenize "`lcols'" local lcolsN = 0 while "`1'" != "" { cap confirm var `1' if _rc!=0 { di in re "Variable `1' not defined" exit _rc } local lcolsN = `lcolsN' + 1 tempvar left`lcolsN' leftLB`lcolsN' leftWD`lcolsN' cap confirm string var `1' if _rc == 0{ gen str `leftLB`lcolsN'' = `1' } if _rc != 0{ cap decode `1', gen(`leftLB`lcolsN'') if _rc != 0{ local f: format `1' gen str `leftLB`lcolsN'' = string(`1', "`f'") replace `leftLB`lcolsN'' = "" if `leftLB`lcolsN'' == "." } } replace `leftLB`lcolsN'' = "" if (`use' != 1) & (`lcolsN' != 1) local colName: variable label `1' if "`colName'"==""{ local colName = "`1'" } // WORK OUT IF TITLE IS BIGGER THAN THE VARIABLE // SPREAD OVER UP TO FOUR LINES IF NECESSARY local titleln = length("`colName'") tempvar tmpln gen `tmpln' = length(`leftLB`lcolsN'') qui summ `tmpln' if `use' == 1 local otherln = r(max) drop `tmpln' // NOW HAVE LENGTH OF TITLE AND MAX LENGTH OF VARIABLE local spread = int(`titleln'/`otherln') + 1 if `spread' > 4{ local spread = 4 } local line = 1 local end = 0 gettoken now remain : colName while `end' == 0 { replace `leftLB`lcolsN'' = `leftLB`lcolsN'' + " " + "`now'" in `line' gettoken now remain : remain if ("`now'" == "") | (`line' == 4) { local end = 1 } if length("`remain'") > `titleln'/`spread' { if `end' == 0 { local line = `line' + 1 } } } if `line' > `maxline' { local maxline = `line' } mac shift } } if "`wt'" == "" { local rcols = "`wtText' " + "`rcols'" label var `wtText' "% Weight" } if "`smooth'" !="" { local rcols = "`modelestText' " + "`rcols'" label var `modelestText' "Smooth Est (`level'% CI)" } if "`stats'" == "" { local rcols = "`estText' " + "`rcols'" label var `estText' "`sumstat' (`level'% CI)" } tempvar extra gen `extra' = " " label var `extra' " " local rcols = "`rcols' `extra'" local rcolsN = 0 if "`rcols'" != "" { tokenize "`rcols'" local rcolsN = 0 while "`1'" != ""{ cap confirm var `1' if _rc!=0 { di in re "Variable `1' not defined" exit _rc } local rcolsN = `rcolsN' + 1 tempvar right`rcolsN' rightLB`rcolsN' rightWD`rcolsN' cap confirm string var `1' if _rc == 0{ gen str `rightLB`rcolsN'' = `1' } if _rc != 0{ local f: format `1' gen str `rightLB`rcolsN'' = string(`1', "`f'") replace `rightLB`rcolsN'' = "" if `rightLB`rcolsN'' == "." } /*if ((`rcolsN' > 2) & ("`wt'`stats'" == "") & ("`smooth'" !="")) | ((`rcolsN' > 1) & (("`wt'`stats'" != "") | ("`smooth'" == ""))) { replace `rightLB`rcolsN'' = "" if (`use' != 1 ) }*/ replace `rightLB`rcolsN'' = "" if (`use' == 0 | `use' == -2 ) local colName: variable label `1' if "`colName'"==""{ local colName = "`1'" } // WORK OUT IF TITLE IS BIGGER THAN THE VARIABLE // SPREAD OVER UP TO FOUR LINES IF NECESSARY local titleln = length("`colName'") tempvar tmpln gen `tmpln' = length(`rightLB`rcolsN'') qui summ `tmpln' if `use' == 1 local otherln = r(max) drop `tmpln' // NOW HAVE LENGTH OF TITLE AND MAX LENGTH OF VARIABLE local spread = int(`titleln'/`otherln')+1 if `spread' > 4{ local spread = 4 } local line = 1 local end = 0 gettoken now remain : colName while `end' == 0 { replace `rightLB`rcolsN'' = `rightLB`rcolsN'' + " " + "`now'" in `line' gettoken now remain : remain if ("`now'" == "") | (`line' == 4) { local end = 1 } if length("`remain'") > `titleln'/`spread' { if `end' == 0 { local line = `line' + 1 } } } if `line' > `maxline'{ local maxline = `line' } mac shift } } // now get rid of extra title rows if they weren't used if `maxline'==3 { drop in 4 } if `maxline'==2 { drop in 3/4 } if `maxline'==1 { drop in 2/4 } egen `newid' = group(`id') replace `id' = `newid' drop `newid' if "`compabs'" != "" { summ `id' if `use'==1 & `groupvar'==1 local startg1 = r(min) local stopg1 = r(max) drop if (`use' == 0 | `use' == -2) & (_n > `startg1' & _n!=_N) egen `newid' = group(`id') replace `id' = `newid' drop `newid' bys `groupvar' : egen `gid' =seq() if `use'==1 | `use'==2 replace `gid' = `gid' + `startg1' - 1 replace `id' = `gid' if `gid'!=. sort `id' `groupvar' cap drop `expand' cap gen `expand' = 1 + 2*(`id'[_n]==`id'[_n-1]) expand `expand', gen(`expanded') gsort `id' `expanded' `groupvar' replace `id' = _n replace `use' = 0 if `expanded' //blanks sort `expanded' `gid' `id' by `expanded' `gid': egen `order' = seq() if !`expanded' & `gid' != . replace `id' = `id' + 0.75 if `order' == 2 sort `id' replace `id' = `id' + 0.75 if _n == 2 } if "`compabs'" != "" { local borderline = `maxline' + 1.5 } else { local borderline = `maxline' + 0.75 } local leftWDtot = 0 local rightWDtot = 0 local leftWDtotNoTi = 0 forvalues i = 1/`lcolsN'{ getlen `leftLB`i'' `leftWD`i'' qui summ `leftWD`i'' if `use' != 3 // DON'T INCLUDE OVERALL STATS AT THIS POINT local maxL = r(max) local leftWDtotNoTi = `leftWDtotNoTi' + `maxL' replace `leftWD`i'' = `maxL' } tempvar titleLN // CHECK IF OVERALL LENGTH BIGGER THAN REST OF LCOLS getlen `leftLB1' `titleLN' qui summ `titleLN' if `use' == 3 local leftWDtot = max(`leftWDtotNoTi', r(max)) forvalues i = 1/`rcolsN'{ getlen `rightLB`i'' `rightWD`i'' qui summ `rightWD`i'' if `use' != 3 replace `rightWD`i'' = r(max) local rightWDtot = `rightWDtot' + r(max) } // CHECK IF NOT WIDE ENOUGH (I.E., OVERALL INFO TOO WIDE) // LOOK FOR EDGE OF DIAMOND summ `lci' if `use' == ... tempvar maxLeft getlen `leftLB1' `maxLeft' qui count if `use' == 2 | `use' == 3 if r(N) > 0 { summ `maxLeft' if `use' == 2 | `use' == 3 // NOT TITLES THOUGH! local max = r(max) if `max' > `leftWDtotNoTi'{ // WORK OUT HOW FAR INTO PLOT CAN EXTEND // WIDTH OF LEFT COLUMNS AS FRACTION OF WHOLE GRAPH local x = `leftWDtot'*(`astext'/100)/(`leftWDtot'+`rightWDtot') tempvar y // SPACE TO LEFT OF DIAMOND WITHIN PLOT (FRAC OF GRAPH) gen `y' = ((100-`astext')/100)*(`lci'-`DXmin') / (`DXmax'-`DXmin') qui summ `y' if `use' == 2 | `use' == 3 local extend = 1*(r(min)+`x')/`x' local leftWDtot = max(`leftWDtot'/`extend',`leftWDtotNoTi') // TRIM TO KEEP ON SAFE SIDE // ALSO MAKE SURE NOT LESS THAN BEFORE! } } local LEFT_WD = `leftWDtot' local RIGHT_WD = `rightWDtot' *local ratio = `astext' // USER SPECIFIED- % OF GRAPH TAKEN BY TEXT (ELSE NUM COLS CALC?) local textWD = (`DXwidth'*(`astext'/(100-`astext'))) /(`leftWDtot' + `rightWDtot') *local textWD = ((100-`astext')/100)*(`DXwidth') / (`DXwidth') *local textWD = ((100-`astext')/100)*(`DXwidth') / (`DXwidth') forvalues i = 1/`lcolsN'{ gen `left`i'' = `DXmin' - `leftWDtot'*`textWD' local leftWDtot = `leftWDtot'-`leftWD`i'' } gen `right1' = `DXmax' forvalues i = 2/`rcolsN'{ local r2 = `i' - 1 gen `right`i'' = `right`r2'' + `rightWD`r2''*`textWD' } local AXmin = `left1' local AXmax = `DXmax' + `rightWDtot'*`textWD' // DIAMONDS tempvar DIAMleftX DIAMrightX DIAMbottomX DIAMtopX DIAMleftY1 DIAMrightY1 DIAMleftY2 DIAMrightY2 DIAMbottomY DIAMtopY gen `DIAMleftX' = `lci' if `use' == 2 | `use' == 3 gen `DIAMleftY1' = `id' if (`use' == 2 | `use' == 3) gen `DIAMleftY2' = `id' if (`use' == 2 | `use' == 3) gen `DIAMrightX' = `uci' if (`use' == 2 | `use' == 3) gen `DIAMrightY1' = `id' if (`use' == 2 | `use' == 3) gen `DIAMrightY2' = `id' if (`use' == 2 | `use' == 3) gen `DIAMbottomY' = `id' - 0.4 if (`use' == 2 | `use' == 3) gen `DIAMtopY' = `id' + 0.4 if (`use' == 2 | `use' == 3) gen `DIAMtopX' = `es' if (`use' == 2 | `use' == 3) replace `DIAMleftX' = `DXmin' if (`lci' < `DXmin' ) & (`use' == 2 | `use' == 3) replace `DIAMleftX' = . if (`es' < `DXmin' ) & (`use' == 2 | `use' == 3) //If one study, no diamond replace `DIAMleftX' = . if (`df' < 2) & (`use' == 2 | `use' == 3) replace `DIAMleftY1' = `id' + 0.4*(abs((`DXmin' -`lci')/(`es'-`lci'))) if (`lci' < `DXmin' ) & (`use' == 2 | `use' == 3) replace `DIAMleftY1' = . if (`es' < `DXmin' ) & (`use' == 2 | `use' == 3) replace `DIAMleftY2' = `id' - 0.4*( abs((`DXmin' -`lci')/(`es'-`lci')) ) if (`lci' < `DXmin' ) & (`use' == 2 | `use' == 3) replace `DIAMleftY2' = . if (`es' < `DXmin' ) & (`use' == 2 | `use' == 3) replace `DIAMrightX' = `DXmax' if (`uci' > `DXmax' ) & (`use' == 2 | `use' == 3) replace `DIAMrightX' = . if (`es' > `DXmax' ) & (`use' == 2 | `use' == 3) //If one study, no diamond replace `DIAMrightX' = . if (`df' == 1) & (`use' == 2 | `use' == 3) replace `DIAMrightY1' = `id' + 0.4*( abs((`uci'-`DXmax' )/(`uci'-`es')) ) if (`uci' > `DXmax' ) & (`use' == 2 | `use' == 3) replace `DIAMrightY1' = . if (`es' > `DXmax' ) & (`use' == 2 | `use' == 3) replace `DIAMrightY2' = `id' - 0.4*( abs((`uci'-`DXmax' )/(`uci'-`es')) ) if (`uci' > `DXmax' ) & (`use' == 2 | `use' == 3) replace `DIAMrightY2' = . if (`es' > `DXmax' ) & (`use' == 2 | `use' == 3) replace `DIAMbottomY' = `id' - 0.4*( abs((`uci'-`DXmin' )/(`uci'-`es')) ) if (`es' < `DXmin' ) & (`use' == 2 | `use' == 3) replace `DIAMbottomY' = `id' - 0.4*( abs((`DXmax' -`lci')/(`es'-`lci')) ) if (`es' > `DXmax' ) & (`use' == 2 | `use' == 3) replace `DIAMtopY' = `id' + 0.4*( abs((`uci'-`DXmin' )/(`uci'-`es')) ) if (`es' < `DXmin' ) & (`use' == 2 | `use' == 3) replace `DIAMtopY' = `id' + 0.4*( abs((`DXmax' -`lci')/(`es'-`lci')) ) if (`es' > `DXmax' ) & (`use' == 2 | `use' == 3) replace `DIAMtopX' = `DXmin' if (`es' < `DXmin' ) & (`use' == 2 | `use' == 3) replace `DIAMtopX' = `DXmax' if (`es' > `DXmax' ) & (`use' == 2 | `use' == 3) replace `DIAMtopX' = . if ((`uci' < `DXmin' ) | (`lci' > `DXmax' )) & (`use' == 2 | `use' == 3) gen `DIAMbottomX' = `DIAMtopX' } // END QUI if "`compabs'" != "" { tempvar strgroupvar decode `groupvar', gen(`strgroupvar') } forvalues i = 1/`lcolsN'{ if "`compabs'" != "" { qui replace `leftLB`i'' = "" if (`expanded') if `i'==1 { qui replace `leftLB`i'' = "" if (`order' == 2 & `use'==1) | (`use' == -2 & `id' == `=`startg1'-1') qui replace `leftLB`i'' = "Mean " + "`groupvar'" + " = " + `strgroupvar' if `use'==2 } } local lcolCommands`i' "(scatter `id' `left`i'', msymbol(none) mlabel(`leftLB`i'') mlabcolor(black) mlabpos(3) mlabsize(`texts'))" } forvalues i = 1/`rcolsN' { if "`compabs'" != "" { qui replace `rightLB`i'' = "" if (`expanded') } local rcolCommands`i' "(scatter `id' `right`i'', msymbol(none) mlabel(`rightLB`i'') mlabcolor(black) mlabpos(3) mlabsize(`texts'))" } if `"`diamopts'"' == "" { local diamopts "lcolor(red)" if "`compabs'" != "" { local diamopts0 "lcolor("0 0 0")" local diamopts1 "lcolor("255 127 0")" } } else { if strpos(`"`diamopts'"',"hor") != 0 | strpos(`"`diamopts'"',"vert") != 0 { di as error "Options horizontal/vertical not allowed in diamopts()" exit } if strpos(`"`diamopts'"',"con") != 0{ di as error "Option connect() not allowed in diamopts()" exit } if strpos(`"`diamopts'"',"lp") != 0{ di as error "Option lpattern() not allowed in diamopts()" exit } local diamopts `"`diamopts'"' } //Box options if "`box'" == "" { local iw = "[aw = _WT]" if `"`boxopts'"' != "" & strpos(`"`boxopts'"',"msy") == 0{ local boxopts = `"`boxopts' msymbol(square)"' } if `"`boxopts'"' != "" & strpos(`"`boxopts'"',"msi") == 0{ local boxopts = `"`boxopts' msize(0.5)"' } if `"`boxopts'"' != "" & strpos(`"`boxopts'"',"mco") == 0{ local boxopts = `"`boxopts' mcolor("180 180 180")"' } if `"`boxopts'"' == "" { local boxopts "msymbol(square) msize(.5) mcolor("180 180 180")" } else{ local boxopts `"`boxopts'"' } } if ("`box'" != "") { local boxopts "msymbol(none)" local iw } //Point options if "`smooth'" != "" { local pointsymbol "msymbol(Oh)" local pointcolor "mcolor("128 128 128")" local pointsize "msize(small)" } else { local pointsymbol "msymbol(O)" local pointcolor "mcolor("0 0 0")" local pointsize "msize(vsmall)" } if `"`pointopts'"' != "" & strpos(`"`pointopts'"',"msy") == 0 { local pointopts = `"`pointopts' `pointsymbol'"' } if `"`pointopts'"' != "" & strpos(`"`pointopts'"',"ms") == 0 { local pointopts = `"`pointopts' `pointsize'"' } if `"`pointopts'"' != "" & strpos(`"`pointopts'"',"mc") == 0 { local pointopts = `"`pointopts' `pointcolor'"' } if `"`pointopts'"' == "" { local pointopts `"`pointsymbol' `pointsize' `pointcolor'"' } else{ local pointopts `"`pointopts'"' } //Smooth Point options if `"`smoothpointopts'"' != "" & strpos(`"`smoothpointopts'"',"msy") == 0 { local smoothpointopts = `"`smoothpointopts' msymbol(D)"' } if `"`smoothpointopts'"' != "" & strpos(`"`smoothpointopts'"',"ms") == 0 { local smoothpointopts = `"`smoothpointopts' msize(vsmall)"' } if `"`smoothpointopts'"' != "" & strpos(`"`smoothpointopts'"',"mc") == 0 { local smoothpointopts = `"`smoothpointopts' mcolor("0 0 0")"' } if `"`smoothpointopts'"' == ""{ local smoothpointopts "msymbol(D) msize(vsmall) mcolor("0 0 0")" if "`compabs'" != "" { local smoothpointopts0 "msymbol(D) msize(vsmall) mcolor("0 0 0")" local smoothpointopts1 "msymbol(D) msize(vsmall) mcolor("255 127 0")" } } else{ local smoothpointopts `"`smoothpointopts'"' } // CI options if `"`ciopts'"' == "" { if "`compabs'" != "" { local ciopts0 = `"lcolor("0 0 0")"' local ciopts1 = `" lcolor("255 127 0")"' } if "`smooth'" != "" { local ciopts = `"`ciopts' lwidth(1.25) lcolor(gs13)"' } else { local ciopts = `"`ciopts' lcolor("0 0 0")"' } } else { if strpos(`"`ciopts'"',"hor") != 0 | strpos(`"`ciopts'"',"vert") != 0{ di as error "Options horizontal/vertical not allowed in ciopts()" exit } if strpos(`"`ciopts'"',"con") != 0{ di as error "Option connect() not allowed in ciopts()" exit } if strpos(`"`ciopts'"',"lp") != 0 { di as error "Option lpattern() not allowed in ciopts()" exit } if "`smooth'" != "" { if strpos(`"`ciopts'"',"lc") == 0 { if "`compabs'" != "" { local ciopts0 = `"`ciopts' lcolor("0 0 0")"' local ciopts1 = `"`ciopts' lcolor("255 127 0")"' } else { local ciopts = `"`ciopts' lcolor(red)"' } } if strpos(`"`ciopts'"',"lw") == 0 { local ciopts = `"`ciopts' lwidth(2)"' } } local ciopts `"`ciopts'"' } //Smooth ci if `"`smoothciopts'"' == "" { local smoothciopts "lcolor("0 0 0")" if "`compabs'" != "" { local smoothciopts0 "lcolor("0 0 0")" local smoothciopts1 "lcolor("255 127 0")" } } else { if strpos(`"`smoothciopts'"',"hor") != 0 | strpos(`"`smoothciopts'"',"vert") != 0{ di as error "Options horizontal/vertical not allowed in ciopts()" exit } if strpos(`"`smoothciopts'"',"con") != 0{ di as error "Option connect() not allowed in ciopts()" exit } if strpos(`"`smoothciopts'"',"lp") != 0 { di as error "Option lpattern() not allowed in ciopts()" exit } if strpos(`"`smoothciopts'"',"lw") == 0 { local smoothciopts = `"`smoothciopts' lwidth(.5)"' } local smoothciopts `"`smoothciopts'"' } // PREDCI options if `"`predciopts'"' == "" { local predciopts "lcolor(red) lpattern(solid)" } else { if strpos(`"`predciopts'"',"hor") != 0 | strpos(`"`predciopts'"',"vert") != 0{ di as error "Options horizontal/vertical not allowed in predciopts()" exit } if strpos(`"`predciopts'"',"con") != 0{ di as error "Option connect() not allowed in predciopts()" exit } if `"`predciopts'"' != "" & strpos(`"`predciopts'"',"lp") == 0 { local predciopts = `"`predciopts' lpattern(solid)"' } if `"`predciopts'"' != "" & strpos(`"`predciopts'"',"lc") == 0{ local predciopts = `"`predciopts' lcolor(red)"' } local predciopts `"`predciopts'"' } // Arrow options if `"`arrowopts'"' == "" { if "`smooth'" != "" { local arrowopts "mcolor(red) lstyle(none)" if "`compabs'" != "" { local arrowopts0 "mcolor("0 0 0") lstyle(none)" local arrowopts1 "mcolor("255 127 0") lstyle(none)" } } else { local arrowopts "mcolor("0 0 0") lstyle(none)" } } else { local forbidden "connect horizontal vertical lpattern lwidth lcolor lsytle" foreach option of local forbidden { if strpos(`"`arrowopts'"',"`option'") != 0 { di as error "Option `option'() not allowed in arrowopts()" exit } } if `"`arrowopts'"' != "" & strpos(`"`arrowopts'"',"mc") == 0{ local arrowopts = `"`arrowopts' mcolor("0 0 0")"' } local arrowopts `"`arrowopts' lstyle(none)"' } // END GRAPH OPTS tempvar tempOv overrallLine ovMin ovMax h0Line if `"`olineopts'"' == "" { local olineopts "lwidth(thin) lcolor(red) lpattern(shortdash)" } qui summ `id' local DYmin = r(min) local DYmax = r(max) + 2 qui summ `es' if `use' == 3 local overall = r(max) if `overall' > `DXmax' | `overall' < `DXmin' | "`ovline'" != "" { // ditch if not on graph local overallCommand "" } else { local overallCommand `" (pci `=`DYmax'-2' `overall' `borderline' `overall', `olineopts') "' } if "`ovline'" != "" { local overallCommand "" } if "`subline'" != "" & "`groupvar'" != "" { local sublineCommand "" qui label list `groupvar' local nlevels = r(max) forvalues l = 1/`nlevels' { summ `es' if `use' == 2 & `groupvar' == `l' local tempSub`l' = r(mean) qui summ `id' if `use' == 1 & `groupvar' == `l' local subMax`l' = r(max) + 1 local subMin`l' = r(min) - 2 qui count if `use' == 1 & `groupvar' == `l' if r(N) > 1 { local sublineCommand `" `sublineCommand' (pci `subMin`l'' `tempSub`l'' `subMax`l'' `tempSub`l'', `olineopts')"' } } } else { local sublineCommand "" } if `"`xline'"' != "" { tokenize "`xline'", parse(",") if "`logscale'" != "" { if "`1'" == "0" { local xlineval = ln(`=10^(-`dp')') } else { local xlineval = ln(`1') } } else { local xlineval = `1' } if "`3'" == "" { local xlineopts = "`3'" } else { local xlineopts = "lcolor(black)" } local xlineCommand `" (pci `=`DYmax'-2' `xlineval' `borderline' `xlineval', `xlineopts') "' } qui { //Generate indicator on direction of the off-scale arro tempvar rightarrow leftarrow biarrow noarrow rightlimit leftlimit offRhiY offRhiX offRloY offRloX offLloY offLloX offLhiY offLhiX gen `rightarrow' = 0 gen `leftarrow' = 0 gen `biarrow' = 0 gen `noarrow' = 0 replace `rightarrow' = 1 if /// (round(`uci', 0.001) > round(`DXmax' , 0.001)) & /// (round(`lci', 0.001) >= round(`DXmin' , 0.001)) & /// (`use' == 1 | `use' == 4) & (`uci' != .) & (`lci' != .) replace `leftarrow' = 1 if /// (round(`lci', 0.001) < round(`DXmin' , 0.001)) & /// (round(`uci', 0.001) <= round(`DXmax' , 0.001)) & /// (`use' == 1 | `use' == 4) & (`uci' != .) & (`lci' != .) replace `biarrow' = 1 if /// (round(`lci', 0.001) < round(`DXmin' , 0.001)) & /// (round(`uci', 0.001) > round(`DXmax' , 0.001)) & /// (`use' == 1 | `use' == 4) & (`uci' != .) & (`lci' != .) replace `noarrow' = 1 if /// (`leftarrow' != 1) & (`rightarrow' != 1) & (`biarrow' != 1) & /// (`use' == 1 | `use' == 4) & (`uci' != .) & (`lci' != .) replace `lci' = `DXmin' if (round(`lci', 0.001) < round(`DXmin' , 0.001)) & (`use' == 1 | `use' == 4) replace `uci' = `DXmax' if (round(`uci', 0.001) > round(`DXmax' , 0.001)) & (`uci' !=.) & (`use' == 1 | `use' == 4) replace `lci' = . if (round(`uci', 0.001) < round(`DXmin' , 0.001)) & (`uci' !=. ) & (`use' == 1 | `use' == 4) replace `uci' = . if (round(`lci', 0.001) > round(`DXmax' , 0.001)) & (`lci' !=. ) & (`use' == 1 | `use' == 4) replace `es' = . if (round(`es', 0.001) < round(`DXmin' , 0.001)) & (`use' == 1 | `use' == 4) replace `es' = . if (round(`es', 0.001) > round(`DXmax' , 0.001)) & (`use' == 1 | `use' == 4) if "`smooth'" != "" { replace `modellci' = `DXmin' if (round(`modellci', 0.001) < round(`DXmin' , 0.001)) & (`use' == 1) replace `modeluci' = `DXmax' if (round(`modeluci', 0.001) > round(`DXmax' , 0.001)) & (`modeluci' !=.) & (`use' == 1 ) replace `modellci' = . if (round(`modeluci', 0.001) < round(`DXmin' , 0.001)) & (`modeluci' !=. ) & (`use' == 1 ) replace `modeluci' = . if (round(`modellci', 0.001) > round(`DXmax' , 0.001)) & (`modellci' !=. ) & (`use' == 1 ) replace `modeles' = . if (round(`modeles', 0.001) < round(`DXmin' , 0.001)) & (`use' == 1 ) replace `modeles' = . if (round(`modeles', 0.001) > round(`DXmax' , 0.001)) & (`use' == 1 ) } summ `id' local xaxislineposition = r(max) local xaxis "(pci `xaxislineposition' `DXmin' `xaxislineposition' `DXmax', lwidth(thin) lcolor(black))" /*Xaxis 1 title */ local xaxistitlex `=(`DXmax' + `DXmin')*0.5' local xaxistitle (scatteri `=`xaxislineposition' + 2.25' `xaxistitlex' "`sumstat'", msymbol(i) mlabcolor(black) mlabpos(0) mlabsize(`texts')) /*xticks*/ local ticksx tokenize "`xtick'", parse(",") while "`1'" != "" { if "`1'" != "," { local ticksx "`ticksx' (pci `xaxislineposition' `1' `=`xaxislineposition'+.25' `1' , lwidth(thin) lcolor(black)) " } macro shift } /*labels*/ local xaxislabels tokenize `lblcmd' while "`1'" != ""{ local xaxislabels "`xaxislabels' (scatteri `=`xaxislineposition'+1' `1' "`2'", msymbol(i) mlabcolor(black) mlabpos(0) mlabsize(`texts'))" macro shift 2 } if "`grid'" != "" { tempvar gridy gridxmax gridxmin gen `gridy' = `id' + 0.5 gen `gridxmax' = `AXmax' gen `gridxmin' = `left1' local betweengrids "(pcspike `gridy' `gridxmin' `gridy' `gridxmax' if `use' == 1 , lwidth(vvthin) lcolor(gs12))" } //prediction if "`prediction'" != "" { gen `ilci' = `lci'[_n-1] gen `iuci' = `uci'[_n-1] replace `ilci' = . if `use' != 4 replace `iuci' = . if `use' != 4 gen `predid' = `id'[_n-1] *replace `id' = `predid' if `use' == 4 local cipred0 "(pcspike `predid' `lci' `predid' `ilci' if `use' == 4 , `predciopts') (pcspike `predid' `uci' `predid' `iuci' if `use' == 4 , `predciopts')" local cipred1 "(pcarrow `predid' `ilci' `predid' `lci' if `leftarrow' == 1 & `use' == 4, `arrowopts') (pcarrow `predid' `iuci' `predid' `uci' if `rightarrow' == 1 & `use' == 4, `arrowopts')" } } // end qui /*===============================================================================================*/ /*==================================== GRAPH ================================================*/ /*===============================================================================================*/ if "`smooth'" != "" { local xboxcenter "`modeles'" local smoothcommands1 "(pcspike `id' `modellci' `id' `modeluci' if `use' == 1 , `smoothciopts')" local smoothcommands2 "(scatter `id' `modeles' if `use' == 1 , `smoothpointopts')" if "`compabs'" != "" { local smoothcommands10 "(pcspike `id' `modellci' `id' `modeluci' if `use' == 1 & `groupvar'==1 , `smoothciopts0')" local smoothcommands11 "(pcspike `id' `modellci' `id' `modeluci' if `use' == 1 & `groupvar'==2 , `smoothciopts1')" local smoothcommands20 "(scatter `id' `modeles' if `use' == 1 & `groupvar'==1, `smoothpointopts0')" local smoothcommands21 "(scatter `id' `modeles' if `use' == 1 & `groupvar'==2, `smoothpointopts1')" } } else { local xboxcenter "`es'" } //Observed CI local cicommand "(pcspike `id' `lci' `id' `uci' if `use' == 1 , `ciopts')" if "`compabs'" != "" { local cicommand1 "(pcspike `id' `lci' `id' `uci' if `use' == 1 & `groupvar'==1, `ciopts0')" local cicommand2 "(pcspike `id' `lci' `id' `uci' if `use' == 1 & `groupvar'==2, `ciopts1')" } //Diamonds if "`compabs'" != "" { local diamondcommand11 "(pcspike `DIAMleftY1' `DIAMleftX' `DIAMtopY' `DIAMtopX' if (`use' == 2 & `groupvar'==1) , `diamopts0')" local diamondcommand12 " (pcspike `DIAMtopY' `DIAMtopX' `DIAMrightY1' `DIAMrightX' if (`use' == 2 & `groupvar'==1) , `diamopts0')" local diamondcommand13 " (pcspike `DIAMrightY2' `DIAMrightX' `DIAMbottomY' `DIAMbottomX' if (`use' == 2 & `groupvar'==1) , `diamopts0')" local diamondcommand14 " (pcspike `DIAMbottomY' `DIAMbottomX' `DIAMleftY2' `DIAMleftX' if (`use' == 2 & `groupvar'==1) , `diamopts0')" local diamondcommand21 " (pcspike `DIAMleftY1' `DIAMleftX' `DIAMtopY' `DIAMtopX' if (`use' == 2 & `groupvar'==2) , `diamopts1')" local diamondcommand22 " (pcspike `DIAMtopY' `DIAMtopX' `DIAMrightY1' `DIAMrightX' if (`use' == 2 & `groupvar'==2) , `diamopts1')" local diamondcommand23 " (pcspike `DIAMrightY2' `DIAMrightX' `DIAMbottomY' `DIAMbottomX' if (`use' == 2 & `groupvar'==2) , `diamopts1')" local diamondcommand24 " (pcspike `DIAMbottomY' `DIAMbottomX' `DIAMleftY2' `DIAMleftX' if (`use' == 2 & `groupvar'==2) , `diamopts1')" local diamondcommand1 "(pcspike `DIAMleftY1' `DIAMleftX' `DIAMtopY' `DIAMtopX' if (`use' == 3) , `diamopts')" local diamondcommand2 "(pcspike `DIAMtopY' `DIAMtopX' `DIAMrightY1' `DIAMrightX' if (`use' == 3) , `diamopts')" local diamondcommand3 "(pcspike `DIAMrightY2' `DIAMrightX' `DIAMbottomY' `DIAMbottomX' if (`use' == 3) , `diamopts')" local diamondcommand4 "(pcspike `DIAMbottomY' `DIAMbottomX' `DIAMleftY2' `DIAMleftX' if (`use' == 3) , `diamopts')" } else { local diamondcommand1 "(pcspike `DIAMleftY1' `DIAMleftX' `DIAMtopY' `DIAMtopX' if ( `use' == 2 |`use' == 3) , `diamopts')" local diamondcommand2 "(pcspike `DIAMtopY' `DIAMtopX' `DIAMrightY1' `DIAMrightX' if (`use' == 2 |`use' == 3) , `diamopts')" local diamondcommand3 "(pcspike `DIAMrightY2' `DIAMrightX' `DIAMbottomY' `DIAMbottomX' if (`use' == 2 |`use' == 3) , `diamopts')" local diamondcommand4 "(pcspike `DIAMbottomY' `DIAMbottomX' `DIAMleftY2' `DIAMleftX' if (`use' == 2 |`use' == 3) , `diamopts')" } //legend if "`compabs'" != "" { local lab0:label `groupvar' 1 local lab1:label `groupvar' 2 local legendon "legend(order(1 2) lab(1 "`groupvar' = `lab0'") lab(2 "`groupvar' = `lab1'") bmargin(zero) size(`texts') cols(2) ring(2) position(5))" } else { local legendoff "legend(off)" } #delimit ; twoway // Draw diamond to make it to construct the legend `diamondcommand11' `diamondcommand21' `overallCommand' `sublineCommand' `xlineCommand' `xaxis' `xaxistitle' `ticksx' `xaxislabels' /*COLUMN VARIABLES */ `lcolCommands1' `lcolCommands2' `lcolCommands3' `lcolCommands4' `lcolCommands5' `lcolCommands6' `lcolCommands7' `lcolCommands8' `lcolCommands9' `lcolCommands10' `lcolCommands11' `lcolCommands12' `rcolCommands1' `rcolCommands2' `rcolCommands3' `rcolCommands4' `rcolCommands5' `rcolCommands6' `rcolCommands7' `rcolCommands8' `rcolCommands9' `rcolCommands10' `rcolCommands11' `rcolCommands12' /*PLOT BOXES AND PUT ALL THE GRAPH OPTIONS IN THERE */ (scatter `id' `xboxcenter' `iw' if `use' == 1, `boxopts' yscale(range(`DYmin' `DYmax') noline reverse) ylabel(none) ytitle("") xscale(range(`AXmin' `AXmax') noline) xlabel(none) yline(`borderline', lwidth(thin) lcolor(gs12)) xtitle("") `legendoff' xtick("")) /*HERE ARE GRIDS */ `betweengrids' /*HERE ARE THE CONFIDENCE INTERVALS */ `cicommand' `cicommand1' `cicommand2' `smoothcommands1' `smoothcommands10' `smoothcommands11' `smoothcommands21' `smoothcommands20' /*ADD ARROWS */ (pcarrow `id' `uci' `id' `lci' if `leftarrow' == 1 & `use' == 1 , `arrowopts') (pcarrow `id' `lci' `id' `uci' if `rightarrow' == 1 & `use' == 1, `arrowopts') (pcbarrow `id' `lci' `id' `uci' if `biarrow' == 1 & `use' == 1, `arrowopts') /*DIAMONDS FOR SUMMARY ESTIMATES */ `diamondcommand1' `diamondcommand11' `diamondcommand21' `diamondcommand2' `diamondcommand12' `diamondcommand22' `diamondcommand3' `diamondcommand13' `diamondcommand23' `diamondcommand4' `diamondcommand14' `diamondcommand24' /*HERE ARE THE PREDICTION INTERVALS */ `cipred0' /*ADD ARROWS */ `cipred1' /*POINTS */ (scatter `id' `es' if `use' == 1 , `pointopts') `smoothcommands2' `overallCommand' ,`fopts' `legendon' ; #delimit cr if "$by_index_" != "" { qui graph dir local gnames = r(list) local gname: word 1 of `gnames' tokenize `gname', parse(".") local gname `1' if "`3'" != "" { local ext =".`3'" } qui graph rename `gname'`ext' `gname'_$by_index_`ext', replace if "`graphsave'" != "" { graph save `graphsave'_$by_index, replace } } else { if "`graphsave'" != "" { di _n graph save `graphsave', replace } } end