Stata Programming Tools
This article will introduce you to some Stata programming tools that are not needed by everyone but are very useful in certain circumstances. The intended audience is researchers who already have a strong Stata foundation.
(If you don’t have that foundation, our Stata training can give it to you, whether you attend our workshops or work though the curriculum on your own.)
Compound Double Quotes
The beginning and ending of a string are normally denoted by double quotes ("string"). This causes problems when the string itself contains double quotes. For example, if you wanted to display the string Hamlet said "To be, or not to be." you could not use the code:
display "Hamlet said "To be, or not to be.""The solution is what Stata calls compound double quotes. When Stata sees `" (left single quote followed by a double quote) it treats what follows as a string until it sees "' (double quote followed by a right single quote). Thus:
display `"Hamlet said "To be, or not to be.""'Capture
On occasion you may expect a command to generate an error under certain circumstances but choose to ignore it. For example, putting log close at the beginning of a do file prevents a previously opened log from interfering with your do file, but generates an error if no log is open—even though not having a log open is exactly the situation you want to create.
The capture prefix prevents Stata from halting your do file if the ensuing command generates an error. The error is “captured” first. Thus:
capture log closewill close any open log but not crash a do file if no log file is open.
The capture prefix should only be used when you fully understand the error the command sometimes generates and why it does so—and you are very confident that that error can be ignored.
When a command is complete it stores a “return code” in _rc. A return code of zero generally means the command executed successfully. You can use capture followed by a branching if based on the return code to have Stata do different things depending on whether an error occurred or not.
Variables in Scalar Contexts
A Stata variable is a vector: it has many values. If you type list x you get a list of all the values of x. However, some contexts call for a scalar. For example, the display command displays just one thing. If a variable is used in a scalar context, the value of the variable for the first observation is used. Thus if you type:
display xyou’ll get just the first value of x, as if you’d typed:
display x[1]We suggest not taking advantage of this behavior, because it makes for confusing code. If a command calls for a scalar and you want that scalar to be the first value of x, type x[1] rather than just x.
This behavior can cause real problems if you don’t realize a particular context calls for a scalar, as you’ll see in the next section.
Branching If
You’re familiar with if conditions at the end of commands, meaning “only carry out this command for the observations where this condition is true.” This is a subsetting if. When if starts a command, it is a branching if and has a very different meaning: “don’t execute the following command or commands at all unless this condition is true.”
The syntax for a single command is:
if <condition> <command>For a block of commands, it’s:
if <condition> {
<commands>
}An if block can be followed by an else block, meaning “commands to be executed if the condition is not true.” The else can precede another if, allowing for else if chains of any length:
if <condition1> {
<commands to execute if condition1 is true>
}
else if <condition2> {
<commands to execute if condition one is false and condition2 is true>
}
else {
<commands to execute if both condition1 and condition2 are false>
}All the conditions used in a branching if have just one value: they are either true or false, period, not true for some observations and false for others. (If you want to execute a command for some observations and not others, that’s a job for a subsetting if.) If you use a variable in a branching if condition, then only the first value will be used. Thus:
if x>5 display "x is greater than 5"will display its message if and only if the value of x for the first observation is greater than 5.
One good use for branching if is handling errors. If you know a command will sometimes fail but can recover from it, you can use:
capture <problem command>
if _rc {
<fix the problem>
}The condition if _rc is equivalent to if _rc != 0, and a return code of zero means the command ran successfully.
While Loops
foreach and forvalues loops repeat a block of commands a set number of times, but while loops repeat them until a given condition is no longer true. For example:
local i 1
while `i'<=5 {
display `i++'
}is equivalent to:
forval i=1/5 {
display `i'
}Note that i is increased by 1 each time through the while loop—if you left out that step the loop would never end.
A very common use for while loops is to repeat a numerical process until it converges.
Programs
A Stata program is a block of code which can be executed at any time by invoking the program’s name. They are useful when you need to perform a task repeatedly, but not all at once. To begin defining a program, type:
program define <name>where <name> is replaced by the name of the program to be defined. Subsequent commands are considered part of the program, until you type:
endThus a basic “Hello World” program is:
program define hello
display "Hello World"
endTo run this program, type hello.
A program cannot be modified after it is defined; to change it you must first drop the existing version with program drop and then define it again. Since a do file run in an interactive session can’t be sure what’s been defined previously, it’s best to capture program drop a program before you define it:
capture program drop hello
program define hello
display "Hello World Again"
endArguments
Programs can be controlled by passing in arguments. An argument can be anything you can put in a macro: numbers, text, names of variables, etc. You pass arguments into a program by typing them after its program name. Thus:
hello Russell Dimondruns the hello program with two arguments: Russell and Dimond. But arguments only matter if the program does something with them—the current version of hello will completely ignore them.
Programs that use arguments should first use the args command to assign them to local macros. The command:
args fname lnameputs the first argument the program received in the macro fname and the second in the macro lname. You can then use those macros in subsequent commands:
capture program drop hello
program define hello
args fname lname
display "Hello `fname' `lname'"
endReturning Values
Your program can return values in the r() or e() vectors, just like official Stata commands. This is critical if your program is intended for use with bootstrap or simulate. To do so, first declare in your program define command that the program is either rclass (puts results in the r() vector) or eclass (puts results in the e() vector):
program define myprogram, rclassWhen you have a result to return, use the return command. The general syntax is:
return <type> <name> = <value>where <type> can be scalar, local or matrix, <value> is what you want to return, and <name> is what you want it to be called. As a trivial example:
return scalar x = 3When the program is complete, you can refer to the result as r(<name>) or e(<name>). Thus if you’ve just run a program containing the above return command, typing:
gen var = r(x)creates a variable var with the value 3.