* tabexp *************************** * Author : Bruno Schoumaker (UCL) * * bruno.schoumaker@uclouvain.be * * May 17, 2013 * * * * version 1.2.1 * ************************************ program tabexp, byable(recall) version 10.0 syntax [varlist(default=none)] [if] [pweight] [, /* */ BVar(varlist) LENgth(integer 3) DATes(string) /* */ WBirth(varname) AGeg(integer 5) CLuster(varname) /* */ TRend(integer 9999) AWF(varname) MINage(integer 15) (MAXage(integer 49)/* */ ENTRY(varname) CYears /* */ SAVETAB(string)/* */ ENDy(integer 9999) /* */ FORCE NODIS RATES FRM ADJExp DV] *------- PRESERVE THE ORIGINAL DATA SET if "`force'"=="" { preserve } *-------- KEEP OBSERVATIONS FOR BYABLE (and if) marksample touse quietly: keep if `touse' quietly : count if `touse' if r(N)==0 { noisily error 2000 } *-------- ERROR MESSAGE FOR AGE GROUPS if `ageg' != 5 & `ageg'!=1 { di as error "age group should be equal to 1 or 5." error 198 exit } *-------- ERROR MESSAGE FOR MIN AND MAXAGE if `minage' > `maxage' { di as error "maxiumum age should be greater or equal to minimum age." error 198 exit } if (`minage'/`ageg') != int(`minage'/`ageg') { di as error "minimum age should be a multiple of the size of the age groups." error 198 exit } *-------- select b3* as default birth variables local b3list b3_01 b3_02 b3_03 b3_04 b3_05 b3_06 b3_07 b3_08 b3_09 b3_10 b3_11 b3_12 b3_13 b3_14 b3_15 b3_16 b3_17 b3_18 b3_19 b3_20 foreach b3 of local b3list { capture confirm var `b3' if _rc==0 { local nb3=`nb3'+1 local nbvar "`nbvar' `b3'" } } if "`bvar'" == "" { local bvar="`nbvar'" } *-------- select v008 as default end date (date of survey) if "`dates'" == "" { local dates="v008" } tokenize "`dates'", parse("-") foreach number of numlist 1/3 { local var`number'="``number''" } local dates=trim("`var1'") if "`var3'"!="" { tempvar datesm gene `datesm'=`dates'-`var3' local dates="`datesm'" } *-------- select v011 as default birth date of women if "`wbirth'" == "" { local wbirth="v011" } *--------select awfactt as default awfactt if "`awf'" != "" { tempvar awfact gene `awfact'=`awf'/100 local awf="`awfact'" } if "`awf'" == "" { tempvar awfact local awfactt_ok=0 capture confirm var awfactt if _rc==0 { local awfactt_ok=1 tempvar check_aw sort awfactt quietly : gene `check_aw'=awfactt[_N]/awfactt[1] if `check_aw'>1 & `check_aw'!=. { di "By default the variable 'awfactt' is used with this data file." di "If you analyse fertility for sub-populations, use the correct all women factor." } } if `awfactt_ok'==1 { quietly : gene `awfact'=awfactt/100 if `check_aw'==. { quietly : replace `awfact'=1 } } if `awfactt_ok'==0 { gene `awfact'=1 } local awf="`awfact'" } *----- use of fractional months if "`frm'"=="frm" { di "fractional months are used. If you want to replicate the results, use 'set seed' before tabexo or tfr2." foreach var of varlist `bvar' `dates' `wbirth' { tempvar run gene `run'=runiform() quietly : replace `var'=`var'+`run' } } *-------- Keep the weight variable in exp local varwei=subinstr("`exp'","=","",1) *-------- select V005 as default weight if nothing quietly { if "`exp'" == "" { local v005_ok=0 capture confirm var v005 if _rc==0 { local v005_ok=1 } if `v005_ok'==1 { local varwei="v005" local weight="pweight" } if `v005_ok'==0 { tempvar wei gene `wei'=1 local varwei="`wei'" di "`exp'" local weight="pweight" } } } if "`varwei'"!="`wei'" { di "weight variable is " "`varwei'" } if "`varwei'"=="`wei'" { di "weights are not used" } *-------- Display variable names if "`dv'"!="" { di "bvar: " "`bvar'" di "dates: " "`dates'" di "wbirth: " "`wbirth'" di "cluster: " "`cluster'" } *-------- select TREND equal to LENgth as default if `trend' == 9999 { local trend=`length' } *-------- error message trend and explanatory variables if `trend' != `length' & "`varlist'"!=""{ di as error "explanatory variables can not currently be combined with the trend option." error 198 exit } *-------- select TREND equal to LENgth as default if `trend' == 9999 { local trend=`length' } if (`length' < `trend') { di as error "check that the interval for trend is smaller or equal to the length of the period." error 198 exit } tempvar check_trend gene `check_trend'=int(`length'/`trend')*`trend' if (`check_trend'!=`length') { di as error "length should be a multiple of trend." error 198 exit } *-------- error message for se without graph or save if ("`se'"=="se" & ("`gr'"=="" & "`gt'"=="" & "`saverates'"=="" & "`savetrend'"=="")) { di as error "se is only allowed with gr, gt, saverates and savetrend." error 198 exit } *-------- selection of endy (TO BE IMPROVED) if `endy'!=9999 { local timend_a=(`endy'-1900+1)*12 if "`dates'"!="" { di "endy replaces date of survey." } } *-------- tokenize savetable for the replace option tokenize "`savetab'", parse(",") foreach number of numlist 1/3 { local var`number'="``number''" } local savetab=trim("`var1'") if "`var3'"=="replace" { local replace_t ", replace" } if "`var3'"!="replace" { local replace_t "" } *-------- SELECT ONLY THE VARIABLES NEEDED FOR THE COMPUTATION OF RATES keep `dates' `bvar' `wbirth' `varwei' `cluster' `awf' `reg' `varlist' `entry' *-------- CREATION OF TEMPORARY VARIABLES tempvar cmcdep origin dates1 mthmin timend case mean_w *--- ageg is the size of agegroups : multiply it by 12 to have it in months local agegm=`ageg'*12 *---mthsp is the interval for trends expressed in months local mthsp=`trend'*12 *-------- CHOICE OF TYPE OF PERIOD *-------- by year before survey - as in DHS reports if "`cyears'"=="" { gene `timend'=`dates'-1 if `endy'!=9999 { quietly : replace `timend'=`timend_a' } tempvar meanend lastm egen `meanend'=mean(`timend') local centry=1900+((`meanend'-(`length'*12/2))/12) local lasty=int((`meanend'-1)/12)+1900 gene `lastm'=int(`meanend')-(`lasty'-1900)*12 local firsty=`lasty'-`length' local firstm=`lastm'+1 if `firstm'==13 { local firstm=1 local firsty=`firsty'+1 } if `endy'==9999 { display "Preparing table of events and exposure for " `length' " year(s) preceding the survey" } if `endy'!=9999 { display "Preparing table of events and exposure for " `length' " year(s) ending in December `endy'" } } *-------- by calendar year : considers timend to be the last month of the last complete year if "`cyears'"=="cyears" { serset create `dates' local mthmin: serset min `dates' gene `timend'=(int((`mthmin'-1)/12))*12 local meanend=`timend' if `endy'!=9999 { replace `timend'=`timend_a' } local lasty=1900+int((`timend'-1)/12) local firsty=`lasty'-`length'+1 local centry=(`lasty'+`firsty')/2+0.5 display "Preparing table of events and exposure for " `length' " calendar year(s) preceding the year of the survey" tempvar lastm gene `lastm'=int(`timend')-(`lasty'-1900)*12 local firstm 1 } if `firsty'!=`lasty' { display "Period covered: " `firstm' "/" `firsty' " to " `lastm' "/" `lasty' } if `firsty'==`lasty' { display "Rates for year " `firsty' } display "Central date is " `centry' ************************************************************ ***** CONSTRUCTION OF DATA SET - PERSON PERIOD & COLLAPSE ** ************************************************************ quietly { *-------- make sure the sum of weights is equal to sample size (first time) egen `mean_w'=mean(`varwei') quietly : replace `varwei'=`varwei'/`mean_w' *-------- RENAME BIRTH VARIABLES *-------- would ideally use tempvar for db - but problem with reshape foreach var of varlist `bvar'* { local i=`i'+1 gene _db`i'=`var' } *-------- DEFINE Caseid cap drop case gene `case'=_n *-------- RESHAPE FROM WIDE TO LONG *-------- create a fictive birth for all women (survey date + 1000) gene _db0=`dates'+1000 reshape long _db, i(`case') j(nume) *-------- selection of observations bys `case' (_db) : keep if _db!=. |(_n==1 & _db==.) *-------- define births (consider missing and fictive biorth as 0) tempvar birth gene `birth'=cond(_db>=`dates'+1000,0,1) *-------- compute rank tempvar rank bys `case' (_db), sort : gene `rank'=_n *-------- STSET DATA *-------- start of the window gene `cmcdep'=`timend'-`length'*12 *-------- date when women reach minage tempvar cmcmin gene `cmcmin'=`minage'*12+`wbirth'-1 *-------- date when women reach maxage+1 tempvar cmcmax gene `cmcmax'=(`maxage'+1)*12+`wbirth'-1 *-------- choosing origin (start of window, entering 15 or date of entry - if marital fertility or other with entry) egen `origin'=rmax(`cmcdep' `cmcmin') *-------- choosing exit (lower of timend or time maxage) tempvar exit egen `exit'=rmin(`timend' `cmcmax') if "`entry'" != "" { replace `origin'=`entry' if `entry'>`origin' } *-------- for twins & triplets = remove small amount of time by `case' (nume), sort: replace _db=_db-0.01 if _db==_db[_n-1] by `case' (nume), sort: replace _db=_db-0.02 if _db==_db[_n-2] *-------- stset data stset _db [`weight'=`varwei'], id(`case') failure(`birth'==1) enter(`origin') origin(time `origin') exit(time `exit') *--- Compute sample size (weighted and unweighted) stdes local vw1=r(N_sub) local ew1=r(tr) stdes, w local vw2=r(N_sub) local ew2=r(tr) } *-------- make sure the sum of weights is equal to sample size (second time - with valid sample) *- either adjust to number of cases (default) or to total exposure (use adjexp) if "`adjexp'"=="" { quietly : replace `varwei'=`varwei'/`vw2'*`vw1' } if "`adjexp'"=="adjexp" { quietly : replace `varwei'=`varwei'/`ew2'*`ew1' } di "Number of cases (women): " `vw1' *-------- SPLITTIING BY AGE AND PERIOD quietly { *-------- split by age groups tempvar duree stsplit `duree', every(`agegm') after(time=`cmcmin') *-------- split by time interval tempvar period stsplit `period', every(`mthsp') after(time=`cmcdep') *-------- select non empty episodes keep if _t!=. *-------- computation of exposure and age variables tempvar exposy age1 age_g gene `exposy'=((_t-_t0)/12) gene `age1'=int(`duree'/12)+`minage' gene `age_g'=int(`age1'/`ageg')*`ageg' egen `dates1'=mean(`dates') replace `dates1'=`dates1'/12 } *-------- COLLAPSE PERSON-PERIOD DATA FILE INTO TABLE OF BIRTHS AND EXPOSURE *-------- adjust exposure by awfact quietly : replace `exposy'=`exposy'*`awf' local lastctry=`meanend' *--------collapse data collapse (sum) _d `exposy' [`weight'=`varwei'], by(`age_g' "`cluster'" `period' "`varlist'") *--------summary info on events and exposure tempvar totpy tot_d egen `totpy'=sum(`exposy') egen `tot_d'=sum(_d) if "`varwei'"!="`wei'" { di "Number of person-years (weighted): " `totpy' di "Number of events (weighted): " `tot_d' } if "`varwei'"=="`wei'" { di "Number of person-years: " `totpy' di "Number of events: " `tot_d' } quietly { rename _d events label var events "Events" rename `age_g' ageg label var ageg "`ageg'-year age groups (value=lower bound)" rename `exposy' exposure label var exposure "Exposure (person-years)" rename `period' period replace period=period/12 } *-------- computation of central years if "`cyears'"=="cyears" { gene centry=period+`trend'/2+`firsty' label var centry "Central date" quietly : levelsof period, local(lper) foreach val of local lper { local perlow=`val' local perlhi=`val'+`trend'-1 local perloh="`perlow'-`perlhi'" if `perlow'==`perlhi'{ local perloh="`perlow'" } label define period `val' "`perloh'", add label var period "Time period (greater=more recent)" } } if "`cyears'"!="cyears" { gene centry=1900+(`lastctry'-(`length'*12)+(`trend'*12/2)+(period)*12)/12 label var centry "Central date" quietly : levelsof period, local(lper) foreach val of local lper { local perlow=`val' local perlhi=`val'+`trend'-1 local perloh="`perlow'-`perlhi'" if `perlow'==`perlhi'{ local perloh="`perlow'" } label define period `val' "`perloh'", add } label var period "Time period (greater=more recent)" } *------- computation of rates and standard errors if "`rates'"=="rates" { gene rate = events/exposure gene se_r=rate/sqrt(events) label var rate "Exposure rate" label var se_r "Standard error of rate" } *-------- saving table of collapsed data if "`savetab'"!="" { local except "`totpy' `tot_d'" quietly : ds local varlist `r(varlist)' local newlist: list varlist - except keep `newlist' save `savetab' `replace_t' } if "`nodis'"=="" { local except "`totpy' `tot_d'" quietly : ds local varlist `r(varlist)' local newlist: list varlist - except list `newlist', noobs clean } *-------- Restore original data if "`force'"=="" { restore } end