*! Reshape a World Development Indicators (WDI) dataset for panel, *! seemingly unrelated regression, or cross-sectional analysis *! Author: P. Wilner Jeanty *! version 1.0 Born: December 2006 *! version 1.1 Updated: November 2007 *! Version 1.2 May 2009: Allows two syntaxes and makes options sercode() and ctycode() required *! version 1.3 November 2009: Allows for quotes in the WDI series descriptors program define wdireshape version 9.2 gettoken usersup:0 if "`usersup'"=="," _wdireshape1 `0' else _wdireshape2 `0' end program define _wdireshape1 version 9.2 syntax, SERName(varname) qui levelsof `sername', local(allsers) local numbv : word count `allsers' di di in y " The current dataset contains `numbv' variables in the following order:" di forv i=1/`numbv' { local lab`i': word `i' of `allsers' di " `i') "`"`lab`i''"'"" // Quotes in the series descriptors properly handled } end program define _wdireshape2 version 9.2 syntax newvarlist, PREPend(string) CTYName(varname) /// SERName(varname) SERCode(varname) /// CTYCode(varname) [BYPer(string) /// STARTyr(string) ENDyr(string) BYVar /// SUR CROS NString(string)] tempvar varid * Check the prepending letter(s) local nlet: length local prepend local err_let=0 local err_j=0 local err_s=0 local s=0 local j=0 forvalue i=97/122 { if char(`i')==substr("`prepend'",1,1) local j=`j'+1 if `nlet'==2 { if char(`i')==substr("`prepend'",2,1) local s=`s'+1 } } if `nlet'<1 | `nlet'>2 local err_let=`err_let'+1 if `j'!=1 local err_j=`err_j'+1 if `nlet'==2 & `s'!=1 local err_s=`err_s'+1 if `err_let'==1 | `err_j'==1 | `err_s'==1 { di di as err "The years must be prepended by one or two letters from a to z" di exit 198 } * Take care of the double dots(..) if present, since they cause numeric variables to be string if "`nstring'"!="" { local nstring=real("`nstring'") unab vars:_all local j=1 foreach var of local vars { local vlab: word `j' of `vars' local var`j' `vlab' if `j'>`nstring' { qui gen double mvar`j'=real(`var') drop `var' ren mvar`j' `var`j'' } local ++j } } * Begin serious stuff local user `prepend' local xxs `ctycode' `ctyname' `sercode' `sername' * Capture the number of variables or series qui levelsof `sername', local(wdi_lab) local maxvar: list sizeof wdi_lab * Now check whether the right number of variable names is supplied in varlist if `maxvar'!= `:word count `varlist'' { di noi di as err " Incorrect number of variable names" di exit 198 } * Now put the WDI labels in individual fabulous macros for later use forv i=1/`maxvar' { local lab`i' :word `i' of `wdi_lab' } egen `varid'=group(`sername') gl wrap reshape local mytxt "Reshaping your dataset" if `"`byvar'"'=="" { if (`"`byper'"' !="" & (`"`startyr'"'=="" | `"`endyr'"'=="")) | /// (`"`startyr'"'!="" & (`"`byper'"' =="" |`"`endyr'"'=="")) | /// (`"`endyr'"'!="" & (`"`byper'"' =="" |`"`startyr'"'=="")) { di di as err "Options {bf:byper()}, {bf:startyr()}, and {bf:endyr()} must be combined" di exit 198 } } if `"`byvar'"'!="" & (`"`byper'"' != "" | `"`startyr'"'!="" | `"`endyr'"' !="") { di di as err "Option {bf:byvar} may not be combined with either {bf:byper()}, {bf:startyr()}, or {bf:endyr()}" di exit 198 } if `"`cros'"'!="" & `"`sur'"'!="" { di di as err "Option {bf:cros} may not be combined with {bf:sur}" exit 198 } if (`"`byvar'"'=="" & `"`byper'"'=="" & `"'startyr'"'=="" & `"`endyr'"' == "") { // if these not specified then try the default: everything at once di noi di as txt "`mytxt' (everything at once), please wait" di capture _resh `varid', prep(`user') sern(`sername') ctyn(`ctyname') serc(`sercode') // Check whether there is sufficient memory to reshape everything at once if c(rc) { if 900 <= c(rc) & c(rc) <= 903 { di as err "Insufficient memory to reshape everything at once, use either {bf:byvar} or {bf:byper()} option." di as err "Or, increase the amount of memory allocated to Stata. See {help memory}. di exit 901 } } } if `"`byvar'"'!="" { di noi di as txt "`mytxt' one variable at a time, please wait" _c di qui { forv i = 1/`maxvar' { tempfile var`i' preserve keep if `varid'==`i' if `"`sercode'"'!="" drop `sercode' `sername' else drop `sername' $wrap long `user', i(`ctyname') j(year) rename `user' `user'`i' so `ctyname' year save `var`i'' restore } use `var1', clear forv i = 2/`maxvar' { merge `ctyname' year using `var`i'' drop _merge so `ctyname' year } } } if (`"`byper'"' !="" & `"`startyr'"'!="" & `"`endyr'"'!="") { local yr1 = real("`startyr'") local yrn = real("`endyr'") local nbyr=`yrn'-`yr1'+1 local ny=real("`byper'") if `ny'!=1 &`ny'!=5 & `ny'!=10 { di di as err "Option {bf:byper()} takes one of 1, 5, and 10." di exit 198 } if `ny'==1 { di noi di as txt "`mytxt' one year at a time, please wait" di forv j=`yr1'/`yrn' { tempfile var`j' preserve keep `varid' `xxs' `user'`j' _resh `varid', prep(`user') sern(`sername') ctyn(`ctyname') serc(`sercode') qui save `var`j'' restore } use `var`yr1'', clear local yr2=`yr1' +1 forv i=`yr2'/`yrn' { append using `var`i'' } so `ctyname' year } else { if `nbyr'<5 & `ny'==5 { di di as err "Cannot reshape five years at a time" di exit 198 } if `nbyr'<10 & `ny'==10 { di di as err "Cannot reshape 10 years at a time" di exit 198 } di noi di as txt "`mytxt' `ny' years at a time" _c di local n=`ny' local endp= cond(mod(`nbyr',`n')<=1,`yr1'+(int(`nbyr'/`n')*`n')-`n',`yr1'+`n'*int(`nbyr'/`n')) forv i=`yr1'(`n')`endp' { tempfile var`i' local j=`n'-1 if mod(`nbyr',`n')==1 & `i'==`endp' { local j=`n' } if mod(`nbyr',`n')>=2 & `i'==`endp' { local j=mod(`nbyr',`n')-1 } local s=`i'+`j' di "Now reshaping period ",`i', "-", `s' preserve keep `varid' `xxs' `user'`i'-`user'`s' capture _resh `varid', prep(`user') sern(`sername') ctyn(`ctyname') serc(`sercode') * Need to check first whether there is sufficient memory to reshape 5 or 10 years at a time if c(rc) { if 900 <= c(rc) & c(rc) <= 903 { di as err /// "Insufficient memory to reshape `n' years at a time, set # to a lower value or use {bf:byvar} option." di as err "Or, increase the memory size. See {help memory}. di exit 901 } } qui save `var`i'' restore } use `var`yr1'', clear local r=`yr1'+`n' forv i=`r'(`n')`endp' { append using `var`i'' } so `ctyname' year } } * Now rename the variables with the user-supplied variable names local i=1 foreach v of local varlist { ren `user'`i' `v' local ++i } if `"`byvar'"' != "" keep `ctyname' `ctycode' year `varlist' la var `ctyname' "Country name" if `"`sur'"' == "" { local ord "order `ctycode'" local labc "la var `ctycode' "Country code"" } if `"`sur'"' == "" & `"`cros'"' == "" { `ord' `labc' egen cid=group(`ctyname') la var cid "Country ID" local i=1 foreach v of local varlist { qui la var `v' "`lab`i''" local ++i } order cid qui xtset cid year di noi di in y "Your dataset has been reshaped and is ready for panel data analysis" } else if `"`sur'"' != "" { qui levelsof `ctyname', local(cty_id) egen cy=group(`ctyname') gen str c="c"+string(cy) drop cy `ctyname' `ctycode' qui $wrap wide `varlist', i(year) j(c) string local i=1 foreach v of local varlist { forv j=1/`:list sizeof cty_id' { local myr :word `j' of `cty_id' local c`j' "`myr'" qui la var `v'c`j' "`c`j'' - `lab`i''" } local ++i } qui tsset year di noi di in y "Your dataset has been reshaped and is ready for SUR analysis" } else if `"`cros'"' !="" { tempvar ci egen `ci'=group(`ctyname') sum year if `ci'==1, meanonly local nt=r(n) local yr1=r(min) local yrn=r(max) qui levelsof year, local(yr_id) qui $wrap wide `varlist', i(`ctyname') j(year) local i=1 foreach v of local varlist { if `nt'==`yrn'-`yr1'+1 { // meaning there are no gaps in the time series forv j=`yr1'/`yrn' { qui la var `v'`j' "`j' - `lab`i''" } } else { // in case there are gaps forv j=1/`:list sizeof yr_id' { local yr_`j' "`:word `j' of `yr_id''" qui la var `v'`yr_`j'' "`yr_`j'' - `lab`i''" } } local ++i } `ord' `labc' di noi di in y "Your dataset has been reshaped and is ready for cross sectional or change analysis" } end program define _resh version 9.2 syntax varlist(max=1), prep(string) sern(varname) ctyn(varname) serc(varname) qui { $wrap long `prep', i(`ctyn' `varlist') j(year) drop `serc' `sern' $wrap wide `prep', i(`ctyn' year) j(`varlist') } end