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.

No comments:

Post a Comment