program define stak *! version 1.2.1 05dec2000 TJS & NJC (hon.) version 6 if "`1'" == "" { di in re "varlist required" di in bl "r(100);" help stak error 100 } syntax varlist [if] [in] [ , /* */ Into(str) Gid(str) Retain Wide Dummy Labels CLEAR ] tokenize `varlist' * convert switch-strings to logicals local retain = "`retain'" == "retain" local wide = "`wide'" == "wide" local dummy = "`dummy'" == "dummy" local labels = "`labels'" == "labels" local clear = "`clear'" == "clear" * check for wide vs dummy conflict if `wide' & `dummy' { di in re "may not specify both wide and dummy; data unchanged" exit 198 } * set new var/grp names if "`into'" == "" { local into _into } if "`gid'" == "" { local gid _gid } if "`into'" == "`gid'" { di in re "INTO varname cannot be same as GID varname;" _c di in re " data unchanged" exit 110 } * set up retain list if `retain' { unab rvars : _all local nvars : word count `varlist' local i = 1 while `i' <= `nvars' { local rvars : subinstr local rvars "``i''" "", word local i = `i' + 1 } } * check for invalid into or gid names unab vr : `varlist' `rvars' local vr : subinstr local vr "`into'" "", word count(local n2) if `n2' { di in re "INTO varname same as a varlist or" _c di in re " retained variable; data unchanged" exit 110 } local vr : subinstr local vr "`gid'" "", word count(local n2) if `n2' { di in re "GID varname same as a varlist or" _c di in re " retained variable; data unchanged" exit 110 } * get # vars to be stacked local nvars : word count `varlist' * check if varlist all numeric or all string local j = 1 local nnum = 0 while `j' <= `nvars' { capture confirm numeric variable ``j'' local nnum = `nnum' + (_rc == 0) local j = `j' + 1 } if `nnum' > 0 & `nnum' < `nvars' { local nstr = `nvars' - `nnum' di in re "cannot stack mixed variables: `nnum' numeric," _c di in re " `nstr' string; data unchanged" exit 198 } if `nnum' == 0 { local strvar 1 } else { local strvar 0 } * preserve data for potential restore preserve * provide a warning before proceeding if `clear' { di in bl "Warning: data in memory will be lost." di in bl " Press any key to continue," _c di in bl " Ctrl-Break to abort." set more 0 more } * set up gid labels cheklab , label(`gid') invars("`varlist' `rvars'") local glab = r(label) local j = 1 while `j' <= `nvars' { local vl : variable label ``j'' if `labels' & "`vl'" != "" /* */ { label define `glab' `j' "`vl'", modify } else { label define `glab' `j' "``j''", modify } local j = `j' + 1 } * copy varlist for later processing if `wide' | `dummy' { local wdvars `varlist' } * prepare the modified data label local dlabel : data label label data "stak: `dlabel'" * data generation loop local j = 1 while `j' <= `nvars' { if `wide' | `dummy' { local wdvar ``j'' } cap drop `into' cap drop `gid' if (`"`if'"' != "" | `"`in'"' != "") /* */ { quietly keep `if' `in' } tempfile new`j' local type : type ``j'' qui gen `type' `into' = ``j'' qui gen int `gid' = `j' if `dummy' { if `strvar' { tempvar v gen `v' = 0 copydes ``j'' `v' drop ``j'' rename `v' ``j'' } qui replace `wdvar' = 1 label values `wdvar' local varlab : variable label `wdvar' label variable `wdvar' "`varlab' dummy" format `wdvar' %8.0g } if `j' == 1 { label values `gid' `glab' } keep `rvars' `into' `gid' `wdvar' qui save "`new`j''" local j = `j' + 1 restore, preserve } * capture all errors capture { * combine temp data sets use "`new1'", replace local j = 2 while `j' <= `nvars' { qui append using "`new`j''" local j = `j' + 1 } * do housekeeping * (blank file name & date, set var labels, complete dummys) global S_FN global S_FNDATE label variable `gid' "group identifiers" label variable `into' "`into' values" if `dummy' { tokenize `wdvars' local j = 1 while `j' <= `nvars' { qui replace ``j'' = 0 if ``j'' == . local j = `j' + 1 } } qui compress order `into' `gid' `wdvars' `rvars' * end capture and, if needed, print note } if _rc { local rc _rc di _n in bl "Note: original data restored" di in ye "(`dlabel')" error `rc' } restore, not exit end program define cheklab, rclass *! version 1.0.0 01dec2000 TJS version 6 syntax , Label(str) Invars(str) tokenize `invars' local j 1 while "``j''" != "" { local vl : value label ``j'' if "`vl'" == "`label'" { local label _gid cap label drop _gid local k 1 while "``k''" != "" { local vl : value label ``k'' if "`vl'" == "`label'" { label value ``k'' } local k = `k' + 1 } return local label = "`label'" exit } local j = `j' + 1 } return local label = "`label'" exit end program def copydes *! from -copydesc- NJC 1.2.1 8 August 2000 version 6.0 syntax varlist(min=2 max=2) tokenize `varlist' args src dst local w : variable label `src' if `"`w'"' == "" { local w "`src'" } label variable `dst' `"`w'"' local srclab : value label `src' capture label val `dst' `srclab' local srcfmt : format `src' capture format `dst' `srcfmt' local chsrc : char `src'[] if "`chsrc'" != "" { tokenize `chsrc' while "`1'" != "" { local schar : char `src'[`1'] char `dst'[`1'] `"`schar'"' mac shift } } end