Qualify your commands with capture
Wednesday, 24 September 2008
Suppose you are assembling a .dta file from disparate pieces of raw data -- an .xls workbook here, a .txt file there -- that must each meet some specific conditions. If you do this in a do-file (as you should, for the sake of reproducibility) you will find it useful to first save each of these components into a tempfile and assemble your tempfiles at the end into the .dta file of interest. Tempfiles reside in memory, and die as soon as your do-file has finished running. That is a very convenient way to avoid hard drive clutter.
Now suppose that your final .dta file does not care if some components are not present -- say because you are building it repeatedly, based on data arriving weekly, and it's OK if some of the components are not present in each week. You would want to make this process a server job (cron job if you're UNIX-minded) but for that you would want to ensure that the do-file will not terminate with an error.
Enter capture. Here's how it works:
foreach i in 1 2 {
local tempfile`i'_ok=0
capture confirm file "`tempfile`i''"
if _rc==0 {
local tempfile`i'_ok=1
}
}
So I'm assuming you have two files of interest. The confirm file command, unqualified, can check if a file exists, but if it does not it will exit with an error. The capture qualifier stores that error away, in a sense. It sends it to the _rc predefined macro, which is equal to 0 if the file exists, and some other positive integer if it does not. The point of qualifying confirm file by capture is to keep your do-file going. You can store the state of the _rc in the locals tempfile`i'_ok shown above, and then based on their values you can do various things with your tempfiles, based on whether they exist:
if `tempfile1_ok'==1 & `tempfile2_ok'==1 {
use "`tempfile1'"
merge `mergevars' using "`tempfile2'"
tab _merge
keep if _merge==3
drop _merge
}
foreach i in 1/2 {
else if `tempfile`i'_ok==1' {
use "`tempfile`i''"
}
}
save myfinalset, replace
}
else {
display "no tempfiles this week, so moving on"
}
That's it. Now your do-file will run unencumbered. Capture can be used for all sorts of checks.
As an aside, you may have noticed that I merged the two files using the local `mergevars'. It's nice to use local macros for things like combinations of variables, file paths, or file names. Declaring them all at the top of your do-files makes for easier code maintenance and code recycling.
No. 1 — September 27th, 2008 at 6:20 pm
If you write long do file, it is likely you do it in logical blocks, and as you go along you check the outcome. I find it more useful to have global, not local macro for paths etc.
No. 2 — October 6th, 2008 at 8:52 pm
What is the difference between globals and macros and scalars other than the identifier? `local' $global
No. 3 — October 6th, 2008 at 9:23 pm
The difference is scope. Local macros live inside a given do-file; they disappear when that do-file finishes running, either because it's done or because of an error. Global macros live inside a given Stata instance. They disappear when you turn Stata off (or you explicitly drop them). If you have a project split into two do-files, where the first calls the second, then any macros that you define in the first as local macros will not be recognized by the second. Sometimes that's what you want. But other times it's useful to have the first file handle all the stuff that needs to be defined once, and just serve it to the second file. If you want to do that, you need global macros.
No. 4 — March 1st, 2010 at 7:29 pm
[...] http://enoriver.net/index.php/2008/09/24/qualify-your-commands-with-capture/ Leave a Comment [...]
No. 5 — August 2nd, 2010 at 10:28 pm
Thanks for this. This is close to what I want to do, but your description isn't general enough.
What if you have an large number of files, not just 2? How do you automate that without having very verbose code?