*** Baseline Characteristics Table: table1.ado *** /* program drop partchart */ program define partchart syntax varlist [if] [in], FILE(string) [SHEET(string) /// catcut(integer 9) constats(string) conprec(integer 2) consep(string asis) catsep(string asis) /// by(varname) cattest(string) contest(string) nobase(varlist)] version 10.0 quietly set more off tempvar touse quietly gen `touse' = 0 quietly replace `touse' = 1 `if' `in' local byvar `by' *quietly capture ssc install unique *quietly capture ssc install mat2txt *quietly capture ssc install lstrfun *quietly capture ssc install tabcount *quietly capture ssc install dataout if "`constats'"=="" { local constats mean sd } if "`sheet'"=="" { local sheet partchartraw } preserve quietly misstable summarize `byvar' if `r(max)'==. local missing *local twowaycount: word count `varlist' clear matrix quietly ds `varlist', has(type string) local strnum: word count of `r(varlist)' if `strnum'!=1 { display as error "String variables (`r(varlist)') not allowed" exit 101 } if "`by'"=="" { quietly summ if `touse' local N=`r(N)' local catcutm1=`catcut'-1 local categ local cont unab allvar: `varlist' foreach x of varlist `allvar' { quietly inspect `x' if `touse' if r(N_unique)<= `catcut' { local categ `categ' `x' } if r(N_unique) > `catcutm1' { local cont `cont' `x' } } if "`categ'" != "" { foreach var of varlist `categ' { quietly summ `var' if `touse' local min = r(min) if (`min' != 0 & `min' != 1) & "`if'"=="" { display as error "Categorical variables (`var') must start at 0 or 1. Use recode, replace, or generate new variable. This doesn't apply when using [if]" exit 121 } local max = r(max) local rangep1 = r(max)-r(min)+1 quietly tabcount `var' if `touse', v(`min'/`max') matrix(matrow) quietly svmat matrow, names(freq`var') quietly tab `var' if `touse' quietly gen pc`var'=100*(freq`var'1/r(N)) quietly replace pc`var' = round(pc`var') quietly gen categorical = 1 in 1/`rangep1' mkmat freq`var'1 pc`var' categorical if categorical==1, matrix(`var') local rownames forvalues j = `min'/`max' { local rownames `rownames' `var'`j' } mat rownames `var' = `rownames' mat colnames `var' = FirstStat SecondStat categorical clear restore preserve } } if "`cont'" != "" { foreach var of varlist `cont' { quietly tabstat `var' if `touse', statistics(`constats') save mat `var'first = r(StatTotal)' mat categoricalmat = (0) mat `var' = `var'first,categoricalmat mat colnames `var' = FirstStat SecondStat categorical mat rownames `var' = `var' clear restore preserve } } foreach var in `nobase' { quietly tab `var', matrow(a) local `var'd=a[1,1] } clear local matorder: subinstr local varlist " " "\", all quietly mat output = `matorder' quietly mat colnames output = FirstStat SecondStat categorical quietly mat2txt, matrix(output) saving(dummyout) replace quietly insheet using "dummyout.txt" , tab clear names case quietly tostring FirstStat SecondStat, replace format(%12.`conprec'f) force quietly replace FirstStat = reverse(substr(reverse(FirstStat),`conprec'+2,.)) if categorical==1 quietly replace SecondStat = reverse(substr(reverse(SecondStat),`conprec'+2,.)) if categorical==1 if `"`consep'"' != "" & regexm(substr(`"`consep'"',2,2),`"""') == 1 { quietly gen smush = FirstStat + `consep' + SecondStat if categorical==0 } else if `"`consep'"' != "" & regexm(substr(`"`consep'"',2,2),`"""') != 1 { quietly gen smush = FirstStat + " " + substr(`"`consep'"',2,1) + SecondStat + substr(`"`consep'"',3,1) if categorical==0 } else { quietly gen smush = FirstStat + " (" + SecondStat + ")" if categorical==0 } if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') == 1 & regexm(`"`catsep'"', "nopercent") != 1 { quietly replace smush = FirstStat + `catsep' + SecondStat + "%" if categorical==1 } else if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') == 1 & regexm(`"`catsep'"', "nopercent") == 1 { quietly replace smush = FirstStat + substr(`"`catsep'"',2,1) + SecondStat if categorical==1 } else if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') != 1 & regexm(`"`catsep'"', "nopercent") != 1 { quietly replace smush = FirstStat + " " + substr(`"`catsep'"',2,1) + SecondStat + "%" + substr(`"`catsep'"',3,1) if categorical==1 } else if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') != 1 & regexm(`"`catsep'"', "nopercent") == 1 { quietly replace smush = FirstStat + " " + substr(`"`catsep'"',2,1) + SecondStat + substr(`"`catsep'"',3,1) if categorical==1 } else { quietly replace smush = FirstStat + " (" + SecondStat + "%)" if categorical==1 } quietly keep v1 smush rename v1 variable rename smush total local op1=_N+1 quietly set obs `op1' quietly replace variable="Sample Size" in `op1' quietly replace total="`N'" in `op1' foreach var in `nobase' { quietly drop if variable=="`var'``var'd'" } if regexm(`"`file'"',`"[.]"') == 0 { export excel using "`file'.xlsx", sheet("`sheet'") sheetreplace } if regexm(`"`file'"',`"xls"') == 1 { export excel using "`file'", sheet("`sheet'") sheetreplace } if regexm(`"`file'"',`"txt"') == 1 { outsheet using "`file'", replace noquote nonames } if regexm(`"`file'"',`"csv"') == 1 { outsheet using "`file'", comma replace nonames } if regexm(`"`file'"',`"tex"') == 1 { dataout, save("`file'") tex replace } quietly capture erase "dummyout.txt" } if "`by'"!="" { local catcutm1=`catcut'-1 local categ local cont unab allvar: `varlist' foreach x of varlist `allvar' { quietly inspect `x' if `touse' if r(N_unique)<= `catcut' { local categ `categ' `x' } if r(N_unique) > `catcutm1' { local cont `cont' `x' } } if "`categ'" != "" { foreach var of varlist `categ' { quietly summ `var' if `touse' local min = r(min) if (`min' != 0 & `min' != 1) & "`if'"=="" { display as error "Categorical variables (`var') must start at 0 or 1. Use recode, replace, or generate new variable. This doesn't apply when using [if]" exit 121 } local max = r(max) local rangep1 = r(max)-r(min)+1 quietly tabcount `var' if `touse', v(`min'/`max') matrix(matrow) quietly svmat matrow, names(freq`var') quietly tab `var' if `touse' quietly gen pc`var'=100*(freq`var'1/r(N)) quietly replace pc`var' = round(pc`var') quietly gen categorical = 1 in 1/`rangep1' mkmat freq`var'1 pc`var' categorical if categorical==1, matrix(`var') local rownames forvalues j = `min'/`max' { local rownames `rownames' `var'`j' } mat rownames `var' = `rownames' mat colnames `var' = FirstStat SecondStat categorical clear restore preserve } } if "`cont'" != "" { foreach var of varlist `cont' { quietly tabstat `var' if `touse', statistics(`constats') save mat `var'first = r(StatTotal)' mat categoricalmat = (0) mat `var' = `var'first,categoricalmat mat colnames `var' = FirstStat SecondStat categorical mat rownames `var' = `var' clear restore preserve } } clear local matorder: subinstr local varlist " " "\", all mat output = `matorder' mat colnames output = FirstStat SecondStat categorical quietly mat2txt, matrix(output) saving(dummyout) replace quietly insheet using "dummyout.txt" , tab clear names case quietly tostring FirstStat SecondStat, replace format(%12.`conprec'f) force quietly replace FirstStat = reverse(substr(reverse(FirstStat),`conprec'+2,.)) if categorical==1 quietly replace SecondStat = reverse(substr(reverse(SecondStat),`conprec'+2,.)) if categorical==1 if `"`consep'"' != "" & regexm(substr(`"`consep'"',2,2),`"""') == 1 { quietly gen smush = FirstStat + `consep' + SecondStat if categorical==0 } else if `"`consep'"' != "" & regexm(substr(`"`consep'"',2,2),`"""') != 1 { quietly gen smush = FirstStat + " " + substr(`"`consep'"',2,1) + SecondStat + substr(`"`consep'"',3,1) if categorical==0 } else { quietly gen smush = FirstStat + " (" + SecondStat + ")" if categorical==0 } if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') == 1 & regexm(`"`catsep'"', "nopercent") != 1 { quietly replace smush = FirstStat + `catsep' + SecondStat + "%" if categorical==1 } else if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') == 1 & regexm(`"`catsep'"', "nopercent") == 1 { quietly replace smush = FirstStat + substr(`"`catsep'"',2,1) + SecondStat if categorical==1 } else if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') != 1 & regexm(`"`catsep'"', "nopercent") != 1 { quietly replace smush = FirstStat + " " + substr(`"`catsep'"',2,1) + SecondStat + "%" + substr(`"`catsep'"',3,1) if categorical==1 } else if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') != 1 & regexm(`"`catsep'"', "nopercent") == 1 { quietly replace smush = FirstStat + " " + substr(`"`catsep'"',2,1) + SecondStat + substr(`"`catsep'"',3,1) if categorical==1 } else { quietly replace smush = FirstStat + " (" + SecondStat + "%)" if categorical==1 } quietly keep smush quietly rename smush total quietly save totaldatadummy, replace quietly capture erase "dummyout.txt" restore preserve *local byvar `: word `twowaycount' of `varlist'' quietly tab `byvar' if `touse', matrow(tabvals) clear quietly svmat tabvals, names(col) if c1[1] != 0 & c1[1] != 1 { display as error "The '""by""' variable (`byvar') values must be sequential integers starting at 0 or 1 (i.e... 0,1,2,3 or 1,2,3,4). Use recode, replace, or generate new variable." exit 121 } local nm = _N-1 forvalues i = 1/`nm' { local j=`i'+1 if c1[`i']+1 != c1[`j'] { display as error "The '""by""' variable (`byvar') values must be sequential integers starting at 0 or 1 (i.e... 0,1,2,3 or 1,2,3,4). Use recode, replace, or generate new variable." exit 121 } } restore preserve quietly levelsof `byvar' if `touse', local(bylevs) local firstbylev : word 1 of `bylevs' local tempbylevs = "`bylevs'" quietly inspect `byvar' if `touse' if r(N_0) > 0 { local bylevs foreach num of numlist `tempbylevs' { local newnum=`num'+1 local bylevs `bylevs' `newnum' } } local bywordcount: word count `bylevs' local lastbylev `: word `bywordcount' of `bylevs'' local varlist: subinstr local varlist "`byvar'" "" local catcutm1=`catcut'-1 local categ local cont unab allvar: `varlist' foreach x of varlist `allvar' { quietly inspect `x' if `touse' if r(N_unique)<= `catcut' { local categ `categ' `x' } if r(N_unique) > `catcutm1' { local cont `cont' `x' } } if "`categ'" != "" { foreach var of varlist `categ' { quietly levelsof(`var') if `touse', local(`var'levs) local wordcount: word count ``var'levs' local lastlev `: word `wordcount' of ``var'levs'' local templastlev = "``var'levs'" quietly inspect `var' if `touse' if r(N_0) > 0 { local temp2lastlev foreach num of numlist `templastlev' { local newnum=`num'+1 local temp2lastlev `temp2lastlev' `newnum' } local lastlevwordcount: word count `temp2lastlev' local lastlev `: word `lastlevwordcount' of `temp2lastlev'' } if "`cattest'" == "exact" { quietly summ `var' if `touse' local min1 = r(min) local max1 = r(max) quietly summ `byvar' if `touse' local min2 = r(min) local max2 = r(max) quietly tabcount `var' `byvar' if `touse', v1(`min1'/`max1') v2(`min2'/`max2') matrix(`var'freqmat) quietly tab `var' `byvar' if `touse', exact local catpval = r(p_exact) } else { quietly summ `var' if `touse' local min1 = r(min) local max1 = r(max) quietly summ `byvar' if `touse' local min2 = r(min) local max2 = r(max) quietly tabcount `var' `byvar' if `touse', v1(`min1'/`max1') v2(`min2'/`max2') matrix(`var'freqmat) quietly tab `var' `byvar' if `touse', chi2 local catpval = r(p) } mat pmat = J(`lastlev', 1, 0) forvalues i = 1/`lastlev' { mat pmat[`i',1] = `catpval' } mat catmat = J(`lastlev',1,1) local tempmatsmush foreach blev of numlist `bylevs' { mat `var'submat`blev' = `var'freqmat[1..`lastlev',`blev'] mat `var'pcmat`blev' = (100/(trace(diag(`var'submat`blev'))))*`var'submat`blev' mat `var'submat`blev'pcmat`blev' = `var'submat`blev' , `var'pcmat`blev' local tempmatsmush `tempmatsmush' `var'submat`blev'pcmat`blev' clear restore preserve } local matsmush : subinstr local tempmatsmush " " "," , all mat `var' = `matsmush',pmat,catmat local colnames forvalues i = 1/`lastbylev' { local colnames `colnames' FirstStat`i' SecondStat`i' } mat colnames `var' = `colnames' pvalue categorical local rownames forvalues j = `min1'/`max1' { local rownames `rownames' `var'`j' } mat rownames `var' = `rownames' } } if "`cont'" != "" { foreach var of varlist `cont' { local tempconmat local firststat: word 1 of `constats' local twostat: word 2 of `constats' if "`firststat'"=="mean" | "`firststat'"=="me" { local firststat1 r(mean) } if "`twostat'"=="mean" | "`twostat'"=="me" { local twostat1 r(mean) } if "`firststat'"=="count" | "`firststat'"=="co" | "`firststat'"=="n" { local firststat1 r(N) } if "`twostat'"=="count" | "`twostat'"=="co" | "`twostat'"=="n" { local twostat1 r(N) } if "`firststat'"=="sum" | "`firststat'"=="su" { local firststat1 r(sum) } if "`twostat'"=="sum" | "`twostat'"=="su" { local twostat1 r(sum) } if "`firststat'"=="max" | "`firststat'"=="ma" { local firststat1 r(max) } if "`twostat'"=="max" | "`twostat'"=="ma" { local twostat1 r(max) } if "`firststat'"=="min" | "`firststat'"=="mi" { local firststat1 r(min) } if "`twostat'"=="min" | "`twostat'"=="mi" { local twostat1 r(min) } if "`firststat'"=="range" | "`firststat'"=="r" { local firststat1 r(max)-r(min) } if "`twostat'"=="range" | "`twostat'"=="r" { local twostat1 r(max)-r(min) } if "`firststat'"=="sd" { local firststat1 r(sd) } if "`twostat'"=="sd" { local twostat1 r(sd) } if "`firststat'"=="variance" | "`firststat'"=="v" { local firststat1 r(Var) } if "`twostat'"=="variance" | "`twostat'"=="v" { local twostat1 r(Var) } if "`firststat'"=="cv" { local firststat1 r(sd)/r(mean) } if "`twostat'"=="cv" { local twostat1 r(sd)/r(mean) } if "`firststat'"=="semean" | "`firststat'"=="sem" { local firststat1 r(sd)/sqrt(r(N)) } if "`twostat'"=="semean" | "`twostat'"=="sem" { local twostat1 r(sd)/sqrt(r(N)) } if "`firststat'"=="skewness" | "`firststat'"=="sk" { local firststat1 r(skewness) } if "`twostat'"=="skewness" | "`twostat'"=="sk" { local twostat1 r(skewness) } if "`firststat'"=="kurtosis" | "`firststat'"=="k" { local firststat1 r(kurtosis) } if "`twostat'"=="kurtosis" | "`twostat'"=="k" { local twostat1 r(kurtosis) } if "`firststat'"=="p1" { local firststat1 r(p1) } if "`twostat'"=="p1" { local twostat1 r(p1) } if "`firststat'"=="p5" { local firststat1 r(p5) } if "`twostat'"=="p5" { local twostat1 r(p5) } if "`firststat'"=="p10" { local firststat1 r(p10) } if "`twostat'"=="p10" { local twostat1 r(p10) } if "`firststat'"=="p25" { local firststat1 r(p25) } if "`twostat'"=="p25" { local twostat1 r(p25) } if "`firststat'"=="p50" | "`firststat'"=="median" | "`firststat'"=="med" { local firststat1 r(p50) } if "`twostat'"=="p50" | "`twostat'"=="median" | "`twostat'"=="med" { local twostat1 r(p50) } if "`firststat'"=="p75" { local firststat1 r(p75) } if "`twostat'"=="p75" { local twostat1 r(p75) } if "`firststat'"=="p90" { local firststat1 r(p90) } if "`twostat'"=="p90" { local twostat1 r(p90) } if "`firststat'"=="p95" { local firststat1 r(p95) } if "`twostat'"=="p95" { local twostat1 r(p95) } if "`firststat'"=="p99" { local firststat1 r(p99) } if "`twostat'"=="p99" { local twostat1 r(p99) } if "`firststat'"=="iqr" { local firststat1 r(p75)-r(p25) } if "`twostat'"=="iqr" { local twostat1 r(p75)-r(p25) } foreach num of numlist `tempbylevs' { quietly summ `var' if `byvar' == `num' & `touse', detail mat `var'first`num' = J(1,2,0) mat `var'first`num'[1,1] = `firststat1' mat `var'first`num'[1,2] = `twostat1' local tempconmat `tempconmat' `var'first`num' } local `var'first : subinstr local tempconmat " " "," , all mat `var'first = ``var'first' if "`contest'"=="kwallis" { quietly kwallis `var' if `touse', by(`byvar') local conpval = chi2tail(r(df),r(chi2_adj)) } else { quietly anova `var' `byvar' if `touse' local conpval = Ftail(e(df_m), e(df_r),e(F)) } mat pmat = (`conpval') mat categoricalmat = (0) mat `var' = `var'first,pmat,categoricalmat local colnames forvalues i = 1/`lastbylev' { local colnames `colnames' FirstStat`i' SecondStat`i' } mat colnames `var' = `colnames' pvalue categorical mat rownames `var' = `var' clear restore preserve } } foreach var in `nobase' { quietly tab `var', matrow(a) local `var'd=a[1,1] } ********************************************* quietly levelsof `byvar' if `touse', local(bylevs) local firstbylev : word 1 of `bylevs' local tempbylevs = "`bylevs'" quietly inspect `byvar' if `touse' if r(N_0) > 0 { local bylevs foreach num of numlist `tempbylevs' { local newnum=`num'+1 local bylevs `bylevs' `newnum' } } local bywordcount: word count `bylevs' local lastbylev `: word `bywordcount' of `bylevs'' quietly tab `byvar' `byvar' if `touse', matcell(a) local lp1=`lastbylev'+2 mat ss = J(1,`lp1',0) quietly summ if `touse' local N=r(N) mat ss[1,2]=`N' forvalues i=3/`lp1' { local j=`i'-2 mat ss[1,`i']=a[`j',`j'] } local colnames forvalues i = 1/`lastbylev' { if "`firstbylev'"=="1" local j=`i' if "`firstbylev'"=="0" local j=`i'-1 local colnames `colnames' `byvar'`j' } mat colnames ss = variable total `colnames' clear quietly svmat ss, names(col) quietly tostring *, replace quietly save "sampsizexxx", replace ************************************************ clear local firstmatorder: subinstr local varlist " " "\", all local lfirstmatorder: length local firstmatorder local uselength = `lfirstmatorder' quietly lstrfun matorder, substr("`firstmatorder'",1,`uselength') mat output = `matorder' local colnames forvalues i = 1/`lastbylev' { local colnames `colnames' FirstStat`i' SecondStat`i' } mat colnames output = `colnames' pvalue categorical quietly mat2txt, matrix(output) saving(dummyout) replace quietly insheet using "dummyout.txt" , tab clear names case forvalues i = 1/`lastbylev' { quietly replace SecondStat`i' = round(SecondStat`i') if categorical==1 quietly tostring FirstStat`i' SecondStat`i', replace format(%12.`conprec'f) force quietly tostring pvalue, replace format(%9.3f) force quietly replace pvalue = "<0.001" if pvalue == "0.000" quietly replace FirstStat`i' = reverse(substr(reverse(FirstStat`i'),`conprec'+2,.)) if categorical==1 quietly replace SecondStat`i' = reverse(substr(reverse(SecondStat`i'),`conprec'+2,.)) if categorical==1 if `"`consep'"' != "" & regexm(substr(`"`consep'"',2,2),`"""') == 1 { quietly gen smush`i' = FirstStat`i' + `consep' + SecondStat`i' if categorical==0 } else if `"`consep'"' != "" & regexm(substr(`"`consep'"',2,2),`"""') != 1 { quietly gen smush`i' = FirstStat`i' + " " + substr(`"`consep'"',2,1) + SecondStat`i' + substr(`"`consep'"',3,1) if categorical==0 } else { quietly gen smush`i' = FirstStat`i' + " (" + SecondStat`i' + ")" if categorical==0 } if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') == 1 & regexm(`"`catsep'"', "nopercent") != 1 { quietly replace smush`i' = FirstStat`i' + `catsep' + SecondStat`i' + "%" if categorical==1 } else if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') == 1 & regexm(`"`catsep'"', "nopercent") == 1 { quietly replace smush`i' = FirstStat`i' + substr(`"`catsep'"',2,1) + SecondStat`i' if categorical==1 } else if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') != 1 & regexm(`"`catsep'"', "nopercent") != 1 { quietly replace smush`i' = FirstStat`i' + " " + substr(`"`catsep'"',2,1) + SecondStat`i' + "%" + substr(`"`catsep'"',3,1) if categorical==1 } else if `"`catsep'"' != "" & regexm(substr(`"`catsep'"',2,2),`"""') != 1 & regexm(`"`catsep'"', "nopercent") == 1 { quietly replace smush`i' = FirstStat`i' + " " + substr(`"`catsep'"',2,1) + SecondStat`i' + substr(`"`catsep'"',3,1) if categorical==1 } else { quietly replace smush`i' = FirstStat`i' + " (" + SecondStat`i' + "%)" if categorical==1 } quietly drop FirstStat`i' SecondStat`i' } quietly drop categorical quietly order v1 smush1-smush`lastbylev' pvalue quietly rename v1 variable forvalues num = 1/`lastbylev' { local minusone = `num' - 1 if `firstbylev' == 0 { quietly rename smush`num' `byvar'`minusone' } if `firstbylev' != 0 { quietly rename smush`num' `byvar'`num' } } quietly keep variable-pvalue quietly merge 1:1 _n using totaldatadummy, nogen quietly order variable total quietly drop if missing(variable) quietly append using "sampsizexxx.dta" local N=_N quietly replace variable="Sample Size" in `N' foreach var in `nobase' { quietly drop if variable=="`var'``var'd'" } if regexm(`"`file'"',`"[.]"') == 0 { export excel using "`file'.xlsx", sheet("`sheet'") sheetreplace firstrow(variables) } if regexm(`"`file'"',`"xls"') == 1 { export excel using "`file'", sheet("`sheet'") sheetreplace firstrow(variables) } if regexm(`"`file'"',`"txt"') == 1 { outsheet using "`file'", replace noquote } if regexm(`"`file'"',`"csv"') == 1 { outsheet using "`file'", comma replace } if regexm(`"`file'"',`"tex"') == 1 { dataout, save("`file'") tex replace } quietly capture erase "dummyout.txt" quietly capture erase "totaldatadummy.dta" quietly capture erase "sampsizexxx.dta" } if "`firststat'"=="" { local firststat mean } if "`twostat'"=="" { local twostat sd } list, noobs sep(1000) table display "*The table contains `firststat's and `twostat's for continuous variables (`cont') and counts and percentages for categorical variables (`categ')." *macro list _all *mat list ss restore end