*! version 1.0 Oktober 5, 2010 @ 13:50:56 UK *! Sequence-Index-Plot showing the modal element at each position * Version 1.0: First version, based on indexplot 1.7, program sqmodalplot version 11 syntax [if] [in] /// [, so se over(varname) tie(string) by(string) gapinclude SUBSEQuence(string) barwidth(string) /// color(string) xtitle(string asis) yscale(string) ylabel(string) ytitle(string) ysize(string) * ] // Sq-Data if `"`_dta[SQis]'"' == `""' { di as error "data not declared as SQ-data; use -sqset-" exit 9 } // if/in if `"`if'"' != `""' { tokenize `"`if'"', parse(" =+-*/^~!|&<>(),.") while `"`1'"' != `""' { capture confirm variable `1' if !_rc { local iflist "`iflist' `1'" } macro shift } } if `"`iflist'"' != `""' CheckConstant `iflist', stop // Over if `"`over'"' != `""' CheckConstant `over', stop else { tempvar over tempname olab gen byte `over':`olab'=1 label define `olab' 1 "All sequences" if "`ysize'" == "" local ysize "ysize(2)" } marksample touse if "`subsequence'" != "" quietly replace `touse' = 0 if !inrange(`_dta[SQtis]',`subsequence') // by if `"`by'"' != `""' { gettoken byvars byopts: by, parse(",") } preserve quietly { // Drop Sequences with Gaps if `"`gapinclude'"' == `""' { tempvar lcensor rcensor gap by `_dta[SQiis]' (`_dta[SQtis]'), sort: gen `lcensor' = sum(!mi(`_dta[SQis]')) by `_dta[SQiis]' (`_dta[SQtis]'): gen `rcensor' = sum(mi(`_dta[SQis]')) by `_dta[SQiis]' (`_dta[SQtis]'): /// replace `rcensor' = ((_N-_n) == (`rcensor'[_N]-`rcensor'[_n])) & mi(`_dta[SQis]') by `_dta[SQiis]' (`_dta[SQtis]'): /// gen `gap' = sum(mi(`_dta[SQis]') & `lcensor' & !`rcensor') by `_dta[SQiis]' (`_dta[SQtis]'): /// replace `touse' = 0 if `gap'[_N]>0 } keep if `touse' if _N == 0 { noi di as text "(No observations)" exit } tempvar episode begin end pointer // Keep Order only if "`so'" == "so" { tempvar torder stepwidth by `_dta[SQiis]' (`_dta[SQtis]'), sort: /// keep if `_dta[SQis]' ~= `_dta[SQis]'[_n-1] by `_dta[SQiis]' (`_dta[SQtis]'), sort: replace `_dta[SQtis]' = _n } // Construct Scale for option SE else if "`se'" == "se" { by `_dta[SQiis]' `_dta[SQis]', sort: keep if _n == 1 fillin `_dta[SQiis]' `_dta[SQis]' by `_dta[SQiis]' (`_dta[SQis]'), sort: replace `_dta[SQtis]' = _n *replace `_dta[SQis]' = . if _fillin drop if _fillin } // Construct modal sequences tempvar n TIE gen byte `n'=1 collapse (sum) `n', by(`_dta[SQtis]' `over' `_dta[SQis]' `byvars') bysort `byvars' `over' `_dta[SQtis]' (`n'): gen byte `TIE' = `n'==`n'[_n-1] | `n'==`n'[_n+1] capture by `byvars' `over' `_dta[SQtis]' (`n'): assert `TIE'==0 if _n==_N if _rc { if "`tie'" == "gap" | "`tie'" == "" { tempvar GAP bysort `byvars' `over' `_dta[SQtis]' (`n'): replace `_dta[SQis]' = . if `TIE'==1 & _n==_N noi di as text "More than 1 mode found at some positions; tie(gap) applied" } else if "`tie'" == "mode" { tempvar MODE bysort `byvars' `over' (`n'): gen byte `MODE' = `_dta[SQis]'[_N] bysort `byvars' `over' `_dta[SQtis]' (`n'): replace `_dta[SQis]' = `MODE' if `TIE'==1 & _n==_N noi di as text "More than 1 mode found at some positions; tie(mode) applied" } else if "`tie'" == "highest" { bysort `byvars' `over' `_dta[SQtis]' `n' (`_dta[SQis]'): /// replace `_dta[SQis]' = `_dta[SQis]'[_N] if `TIE'==1 noi di as text "More than 1 mode found at some positions; tie(highest) applied" } else if "`tie'" == "lowest" { bysort `byvars' `over' `_dta[SQtis]' `n' (`_dta[SQis]'): /// replace `_dta[SQis]' = `_dta[SQis]'[1] if `TIE'==1 noi di as text "More than 1 mode found at some positions; tie(lowest) applied" } } by `byvars' `over' `_dta[SQtis]' (`n'): keep if _n==_N if "`tie'" == "lead" { bysort `byvars' `over' (`_dta[SQtis]'): replace `_dta[SQis]' = `_dta[SQis]'[_n+1] if `TIE'==1 noi di as text "More than 1 mode found at some positions; tie(lead) applied" } else if "`tie'" == "lag" { bysort `byvars' `over' (`_dta[SQtis]'): replace `_dta[SQis]' = `_dta[SQis]'[_n-1] if `TIE'==1 noi di as text "More than 1 mode found at some positions; tie(lag) applied" } // Number episodes by `byvars' `over' (`_dta[SQtis]'), sort: gen `episode' = 1 /// if `_dta[SQis]' ~= `_dta[SQis]'[_n-1] by `byvars' `over' (`_dta[SQtis]'): replace `episode' = sum(`episode') // Keep 1st and last observation of each `Episode' by `byvars' `over' `episode' (`_dta[SQtis]'), sort: keep if _n==1 | _n==_N // Expand if 1st and last is the same by `byvars' `over' `episode' (`_dta[SQtis]'): gen byte `pointer' = _N==1 expand 2 if `pointer' // generate the time of `begin' and `end' of `episode' by `byvars' `over' `episode' (`_dta[SQtis]'), sort: gen `begin' = `_dta[SQtis]'[1] -.5 by `byvars' `over' `episode' (`_dta[SQtis]'), sort: gen `end' = `_dta[SQtis]'[2] + .5 // procede as shown in Kohler/Brzinsky (2005) if "`barwidth'" == "" local barwidth barwidth(.8) else local barwidth barwidth(`barwidth') levelsof `_dta[SQis]', local(K) local i 1 foreach k of local K { local suffix: subinstr local k "-" "M", all local suffix: subinstr local suffix "." "X", all tempvar bsq`suffix' esq`suffix' gen `bsq`suffix'' = `begin' if `_dta[SQis]' == `k' gen `esq`suffix'' = `end' if `_dta[SQis]' == `k' local legorder `"`legorder' `i' `"`:label (`_dta[SQis]') `k''"'"' local colopt `"color(`:word `i++' of `color'')"' local rbars "`rbars' (rbar `bsq`suffix'' `esq`suffix'' `over', horizontal `colopt' `barwidth')" } // Graph defaults if `"`xscale'"' == `""' { sum `begin', meanonly local min = r(min) sum `end', meanonly local max = r(min) local xscale "xscale(range(`min' `max'))" } if `"`yscale'"' == `""' local yscale `"yscale(reverse)"' else local yscale `"yscale(`yscale')"' if `"`ylabel'"' != `""' local ylabel `"ylabel(`ylabel')"' else if `"`ylabel'"' == `""' { levelsof `over', local(olevels) local ylabel ylabel(`olevels', valuelabel angle(0)) } if `"`xtitle'"' == `""' local xtitle `"xtitle("")"' else local xtitle `"xtitle(`xtitle')"' if `"`ytitle'"' == `""' local ytitle `"ytitle("")"' else local ytitle `"ytitle(`ytitle')"' if `"`legend'"' == `""' local legend `"legend(order(`legorder') col(1) pos(2))"' if `"`by'"' != `""' { if `"`byopts'"' == `""' local byopts `", legend(pos(2) yrescale)"' local by `"by(`byvars' `byopts')"' } // The graph graph twoway `rbars' , /// `legend' `by' /// `yscale' `ylabel' `ytitle' `ysize' /// `xscale' `xtitle' `options' } end program CheckConstant, rclass syntax varlist(default=none) [, stop] sort `_dta[SQiis]' foreach var of local varlist { capture by `_dta[SQiis]': assert `var' == `var'[_n-1] if _n != 1 if _rc & "`stop'" == "" { di as res "`var'" as text " is not constant over time; not used" local varlist: subinstr local varlist "`var'" "", word } if _rc & "`stop'" != "" { di as error "`var' is not constant over time" exit 9 } if "`stop'" == "" { return local checked "`varlist'" } } end