## Friday, June 8, 2012

### Stata Programming Basics - capture command

* Stata Programming Basics - capture command

* I have found the capture command to be an extremely useful staple in countless commands and combinations of commands.

* I usually abbreviate it as cap.

* The most basic function of capture is to run code that if it hits an error it will skip over.

* for example:
hist varaible_that_does_not_exist

* This breaks the execution of the code

* However, sticking a capture in front of it does not
cap hist varaible_that_does_not_exist

* Capture also supresses output which is not always appreciated

* You may want to know why the code did not run.

cap noi hist varaible_that_does_not_exist

* This code now displays the error but does not stop the execution of the code.

* Sometimes you might want to know what the particular error code is.

di _rc " is the error code generated by the above command"

* A _rc==0 is generated if the capture code is run succsessfully.

cap noi di "For instance"
di "_rc == "_rc " - so we are error free"

* Capture can also be used to cover a block of code.

cap noi {
di "Capture will keep runing this code until it encounters an error"
di "At that point it will display the error and stop running the code"
I_am_an_error!
di "This will not be displayed because when faced with an error capture goes to the end of the bracket"
}

* Capture can also be combined in this way with a loop
set seed 101
clear
set obs 100

local num_var = rpoisson(50)
* Draw a random count variable with mean equal to 50 and variance equal to 50.

* We want to generate a hypathetical data set which has a number of variables that count from 1 to num_var' with some missing to begin with.

* The following code will generate up to num_var' number of variables.

cap forv i=1(1)num_var' {
* However there is a 10% chance this variable was dropped in the creation step.
local dropped = rbinomial(1,.1)

* If this variable was not dropped generate it as a random normal with mean equal to 0 and standard deviation equal to i'
if dropped'==0 gen var_i'=i'*rnormal()
}

* We can see that now we have a list of variables which has some of them missing.

* Now let's imagine we would like to rename them all a new name.

* We want the simulation to loop through all num_var' integers and rename each of the variables but not stop if it runs into a missing variable.

* To create this list we will use a forvalues loop.  To learn more about that see the forvalues post.

forv i=1(1)num_var' {
cap {
rename var_i' newvar_i'
label var newvar_i' "Random normal: standard deviation i'"
}
* Now let us show a result if the variable was not found
if _rc != 0 di "var_i' not found; var_i' not renamed'"
}

* This is only a small sampling of the potential uses of capture.

set seed 101
clear
set obs 100

* Imagine we are once renaming a lot of variables in many different files but we don't know how many variables are in each file.

local num_var = rpoisson(50)

cap forv i=1(1)num_var' {
gen var_i'=i'*rnormal()
}

* But we do know that there are no missing variables.

* We could look through each of the files and find the last variable number for each.

* Or we could do the following code.

cap
* This is just to set _rc initially to be 0
di _rc

* Set the count variable i to start at 1
local i=1
while _rc==0 {
cap {
rename var_i' newvar_i'
label var newvar_i' "Random normal: standard deviation i'"
}
local i=i'+1
}

* Imagine that you have some string variables mixed in with you numeric variables.

* And you want to recode all of your values that are less than 0 to be equal to zero (bottom coding).

* First lets add some string variables
local i=1
cap
while _rc==0 {
* Approximately 50% of your variables will not be strings
local string = rbinomial(1,.5)
cap noi if string'==1 {
tostring newvar_i', replace force
label var newvar_i' "I am now a string"
}
local i=i'+1
}
* So 50% of the variables are now strings

* Plus we have two variables which are strings that cannot be turned into numbers (and we would not want them to be)
gen rand_string = "asdf"
gen rand_string2 = "asdf2"

* Now what we want to do is go through the data

* Convert our strings to numbers where possible and to recode all of out values less than zero to zero.

* We will use a foreach command to loop through all of our variables now:

foreach v of varlist * {
cap noi destring v', replace
* This converts your strings back to numbers
cap noi replace v'=max(0,v')
* This makes it so that the variable v must have a minimum value of 0.
* Strangely to accomplish this you may take the max function.
* There is of course other ways of doing this
* cap noi replace v'=0 if v'<0
* Would have done the same thing.
}

* I hope this post has been useful.  As is probably very clear there are countless uses to the capture command.  It is therefore extremely useful to learn how it works.