<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Stata Things &#187; macros</title>
	<atom:link href="http://enoriver.net/index.php/tag/macros/feed/" rel="self" type="application/rss+xml" />
	<link>http://enoriver.net</link>
	<description>computing for fun and profit</description>
	<lastBuildDate>Fri, 13 Aug 2010 20:42:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Another use for local macros: Stata graphs</title>
		<link>http://enoriver.net/index.php/2009/04/14/another-use-for-local-macros-stata-graphs/</link>
		<comments>http://enoriver.net/index.php/2009/04/14/another-use-for-local-macros-stata-graphs/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 19:25:32 +0000</pubDate>
		<dc:creator>Gabi Huiber</dc:creator>
				<category><![CDATA[Stata]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[macros]]></category>

		<guid isPermaLink="false">http://enoriver.net/?p=643</guid>
		<description><![CDATA[Graphs are tricky beasts in every programming environment. There are so many ways in which you might want them that any command for drawing them will have to be laden with options and it will probably run over numerous lines. Stata, from version 8 onward, has done a wonderful job of taking the pain out [...]]]></description>
			<content:encoded><![CDATA[<p>Graphs are tricky beasts in every programming environment. There are so many ways in which you might want them that any command for drawing them will have to be laden with options and it will probably run over numerous lines.</p>
<p>Stata, from version 8 onward, has done a wonderful job of taking the pain out of the process as much as practical. The Stata 10 graphics menu is a sight to behold and the ability to click-and-edit graphs interactively, if you haven't tried it yet, will blow your mind. Better yet, anything you do interactively leaves a command trail that you can save, so next time you need the same graph you can just run the command counterpart.</p>
<p>Still, the topic is heavy enough to warrant its own <a href="http://www.stata-press.com/books/vgsg.html">book</a> and you probably will want to buy it. What I'm proposing here is just one option for mass-producing graphs and changing them in bulk, as needed.</p>
<p>If you ever looked at a graph command, you may have noticed that the commands for three or four graphs that show different facets of the same analysis, maybe feeding off the same data set, have pretty large common chunks. I did, and I thought it'd be nice if these common chunks showed up in only one place where if I need to edit them I can do so once and for all.</p>
<p>Local macros can accomplish that. You store parts of a full command in separate strings, some common, some specific to each graph, and save these strings as locals. Calling the graph command is then simply a matter of chaining all these locals back together.</p>
<p>Here's some code that does that for three different graphs, each with some quirk that needs to be accommodated:<br />
<code><br />
// all graphs to draw<br />
local graphs    "retention cos revenue"<br />
</code><code><br />
// graphs for only the test group<br />
local lilgraphs "cos revenue"<br />
</code><code><br />
// graph titles<br />
local retention_title  "Retention rates by target cohort, oldest first"<br />
local cos_title       "Changes of service by snapshot date"<br />
local cos_subtitle    "Accounts on a different FOD from when targeted"<br />
local revenue_title   "Current revenue per targeted subscriber"<br />
</code><code><br />
// var labels<br />
label var count_then     "Accounts targeted"<br />
label var cos            "Change of service"<br />
label var retention_rate "Retention rate"<br />
label var age            "Days since targeted"<br />
label var control        "Group"<br />
label var date_target    "Snapshot date"<br />
label var revenue_pc_now "Average revenue per targeted subscriber"<br />
label var count_now      "Targeted subscribers now active"<br />
foreach time in then now {<br />
  format count_`time' %6.0fc<br />
}<br />
label define control_label 0 "Control Accounts" 1 "Targeted Accounts"<br />
label values control control_label<br />
levelsof date_target, local(date_ticks) // note 1 <br />
</code><code><br />
// generic graph settings<br />
local xtick_settings_1 "xtick(none) xlabel(none) xmtick(`date_ticks')" // note 2<br />
local xtick_settings_2 "xmlabel(`date_ticks', angle(vertical) labsize(small))"<br />
local xtick_settings   "`xtick_settings_1' `xtick_settings_2'"<br />
local ytick_settings_1 "ylabel(,angle(horizontal) labsize(small) axis(1))"<br />
local ytick_settings_2 "ylabel(,angle(horizontal) labsize(small) axis(2))"<br />
local legend_settings  "legend(cols(1))"<br />
</code><code><br />
// specific graph settings<br />
foreach gph in `graphs' {<br />
  local title        "title("``gph'_title'")"<br />
  local subtitle     "subtitle("``gph'_subtitle'", size(small))" // note 3<br />
  local `gph'_title  "`title' `subtitle' "<br />
  local `gph'_saving "saving("`report_to'`gph'_`date'.gph", replace)"<br />
}<br />
local style          "twoway line"<br />
local retention_line "`style' retention_rate age, by(control, `retention_title') "<br />
local cos_line       "`style' cos date_target, `cos_title' "<br />
local revenue_line_1 "`style' revenue_pc_now date_target || "<br />
local revenue_line_2 "line count_now date_target, yaxis(2) `revenue_title' "<br />
local revenue_line   "`revenue_line_1' `revenue_line_2'"<br />
</code><code><br />
local retention_ticks "`ytick_settings_1'"<br />
local cos_ticks       "`xtick_settings' `ytick_settings_1'"<br />
local revenue_ticks   "`cos_ticks' `ytick_settings_2' `legend_settings'"<br />
</code><code><br />
// assemble complete commands<br />
foreach gph in `graphs' {<br />
  local `gph'_graph "``gph'_line' ``gph'_ticks' ``gph'_saving'"<br />
}<br />
</code><code><br />
// draw retention graph<br />
`retention_graph'<br />
</code><code><br />
preserve<br />
keep if control==1<br />
sort date_target<br />
levelsof date_target, local(date_ticks)<br />
</code><code><br />
// draw test group graphs<br />
foreach gph in `lilgraphs' {<br />
  ``gph'_graph'<br />
}<br />
restore</code></p>
<p>The code above is part of a larger effort to keep daily newspapers in business, to which I am a contributor. I had to draw up some reports for a client -- a media company that runs a bunch of local papers -- to show the status report for an experiment in subscriber retention started a while back. Certain subsets of monthly cohorts of subscribers are selected into a target and a control group, we do some magic to the target group, and then compare its retention, revenue, and change-of-service (cos) behavior to that of the control group. </p>
<p>The cos and revenue graphs above need only use a subset of data in this case. The revenue graph is the kind with two y-axes, with average revenue per subscriber tracked along the first y axis and count of active subscribers tracked along the second. The common x axis is time.</p>
<p>Look at the block of code labeled "generic graph settings". Never mind the two separate xtick_settings locals. I am only defining them in order to trade width from length. For the purpose of this blog, I want my code to fit properly inside the column. I am stringing them together immediately afterwards as `xtick_settings'. The two `ytick_settings_' locals are a different matter, however. I need them both for the revenue graph (since it has two y-axes) and I need only the first for the retention and cos graphs. To see how that works later on, notice the difference in the definitions of the `cos_ticks' and `revenue_ticks' locals.</p>
<p>Now look at the in-line comments "note 1" and "note 2". Stata, by default, will keep you from cluttering your axes with too many tick marks and a jumble of overlapping labels. That's nice, but not what I want in this case. These are small graphs and I want every point on the x-axis ticked and labeled. I collect the labels on the line marked "note 1" as the list `date_ticks' and then use them as arguments for the xmtick() and xmlabel() options on the line marked "note 2" and the one below it.</p>
<p>If you look at the block of code labeled "graph titles" you will notice that only the cos graph has a subtitle. That's OK. Stata won't kick up a fuss if you invoke a missing subtitle. That is what I do in the line marked with the in-line comment "note 3".</p>
<p>Now all I need to do is assemble these pieces into full graph commands. Notice the line below the comment "draw retention graph": all of your graph command, with options and everything, fits into that little `retention_graph' local. Of course the point is not to hide your command away. It's to make the chunks available for editing in blocks that make sense. If you need to change the title of a graph, it's easier to look for it in a block of local definitions clearly labeled <code>// graph titles</code> than it would be to go fishing for it inside big messy graph commands. But the bigger gain is that you get to re-use common chunks: everything in the block labeled "generic graph settings" needs to be changed only in one place and applies everywhere, and even some of the "specific graph settings" can be thought of that way.</p>
<p>Of course, you don't want to go through this exercise in abstraction for every occasional graph. This stuff is strictly for mass production. You've got to be able to justify to the client a fixed cost of this size.</p>
]]></content:encoded>
			<wfw:commentRss>http://enoriver.net/index.php/2009/04/14/another-use-for-local-macros-stata-graphs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fun with display and macros</title>
		<link>http://enoriver.net/index.php/2008/12/12/fun-with-display-and-macros/</link>
		<comments>http://enoriver.net/index.php/2008/12/12/fun-with-display-and-macros/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 20:14:53 +0000</pubDate>
		<dc:creator>Gabi Huiber</dc:creator>
				<category><![CDATA[Stata]]></category>
		<category><![CDATA[date and time functions]]></category>
		<category><![CDATA[macros]]></category>

		<guid isPermaLink="false">http://enoriver.net/?p=387</guid>
		<description><![CDATA[Turns out anything you can display -- or di -- on the screen, you can also send to a macro to use later. How useful is that? Well, sometimes you need to say the same thing in different ways. The macro may be set to capture either the form or the substance, depending on which [...]]]></description>
			<content:encoded><![CDATA[<p>Turns out anything you can <code>display</code> -- or <code>di</code> -- on the screen, you can also send to a macro to use later. How useful is that? Well, sometimes you need to say the same thing in different ways. The macro may be set to capture either the form or the substance, depending on which one you need.</p>
<p>I don't usually use macros that way (OK, I wasn't even aware of the possibility until today) but today that need arose, so here's what I learned.</p>
<p>One example of the difference between a thing's looks and substance would be this:<br />
<code><br />
di c(current_date)<br />
</code><br />
What you see on the screen -- today that would be the string "12 Dec 2008" -- is different from what's behind it -- the value 17878, <em>i.e.</em>, the number of days since January 1, 1960.</p>
<p>So you could simply do<br />
<code><br />
local mydate c(current_date)<br />
di "`mydate'"<br />
</code><br />
This looks useful, and maybe it is. The local macro `mydate' above has stored the look of c(current_date), but it knows nothing about its content. You could change that if you defined that macro like this:<br />
<code><br />
local mydate=date(c(current_date),"DMY")<br />
di `mydate'<br />
</code><br />
So `mydate' is now a number, not a string. Specifically, it's an actual date -- from which you can derive things like <code>week(`mydate')</code> or <code>dow(`mydate')</code> or what have you.</p>
<p>But a look of this content, as opposed to the content itself, might be exactly what you want. For example, you may want the YYYYMMDD equivalent of today's date. Easy:<br />
<code><br />
local mydate: di %tdCYND date(c(current_date),"DMY")<br />
di `mydate'</code></p>
<p>So much about that. It's Friday, can't work too hard.</p>
]]></content:encoded>
			<wfw:commentRss>http://enoriver.net/index.php/2008/12/12/fun-with-display-and-macros/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Data from MS Access to Stata</title>
		<link>http://enoriver.net/index.php/2008/11/21/data-from-ms-access-to-stata/</link>
		<comments>http://enoriver.net/index.php/2008/11/21/data-from-ms-access-to-stata/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 06:38:15 +0000</pubDate>
		<dc:creator>Gabi Huiber</dc:creator>
				<category><![CDATA[Stata]]></category>
		<category><![CDATA[global macros]]></category>
		<category><![CDATA[macros]]></category>
		<category><![CDATA[MS Access]]></category>
		<category><![CDATA[odbc load]]></category>

		<guid isPermaLink="false">http://enoriver.net/?p=305</guid>
		<description><![CDATA[In my oldest post about the odbc load command I mentioned that you can pretty easily read data from MS Access into Stata, and even execute SQL commands from within Stata, but I dismissed the whole thing a bit too lightly. A recent look on Google Analytics showed that some people came here looking for [...]]]></description>
			<content:encoded><![CDATA[<p>In my oldest post about the <code>odbc load</code> command I mentioned that you can pretty easily read data from MS Access into Stata, and even execute SQL commands from within Stata, but I dismissed the whole thing a bit too lightly. A recent look on Google Analytics showed that some people came here looking for that sort of information and, judging by how fast they left, they didn't find what they were looking for. So here's another try.</p>
<p>Some context first: one of my ongoing projects is a suite of Stata do-files for helping certain daily newspapers optimize their subscriber retention, using survival analysis. I have several clients. Some of their needs are common, so they can be met with one do-file, others are not so common, so they need custom code. I use global macros as bridges between custom and common code. You need this introduction to see what I'm doing in my example below.</p>
<p>One client is sending me a weekly snapshot of its subscriber database in the MS Access format, in a file called Submaster_YYYYMMDD.mdb. Suppose that that file resides in c:/data/my access file comes from here/. Then I must read it into Stata and save it as subsYYYYMMDD.dta in c:/data/my stata file goes here/. Now suppose that I spread this project across several do-files, so I use some internal names for these file paths in the form of global macros defined once:</p>
<p><code><br />
global datafrom "c:/data/my access file comes from here/"<br />
global datato    "c:/data/my stata file goes here/"<br />
</code></p>
<p>Also suppose that I save the date of arrival part of the file name, YYYYMMDD, as a global macro:</p>
<p><code><br />
global t "YYYYMMDD"<br />
</code></p>
<p>Finally, I don't want my lines to be too long, so I use local macros to compress things a bit whenever that looks practical. Now let's have a look at the actual example:</p>
<p><code><br />
capture confirm file "${datato}subs${t}.dta"<br />
if _rc!=0 {<br />
</code><code><br />
   local mdbpath  "${datafrom}"<br />
   local mdbname "Submaster"<br />
   local source   "MS Access Database;DBQ=`mdbpath'`mdbname'_${t}.mdb"<br />
   capture confirm file "`mdbpath'`mdbname'_${t}.mdb"<br />
</code><code><br />
   if _rc==0 {<br />
      #delimit ;<br />
      local vars "<br />
      ${${paper}index},<br />
      prod_code,<br />
      start_orig,<br />
      last_start_date,<br />
      last_stop_date,<br />
      expire_date,<br />
      rate_table,<br />
      paper_code,<br />
      rate,<br />
      credit_card_usage";<br />
</code><code><br />
      drop _all;<br />
      odbc load,<br />
      exec("SELECT `vars' FROM `table' WHERE (prod_code='1D' OR prod_code='3D')")<br />
      dsn("`source'");<br />
      save "${datato}subs${t}", replace;<br />
      #delimit cr<br />
   }<br />
}<br />
</code></p>
<p>First, I check if the Stata file subsYYYYMMDD.dta exists in the path ${datato} with "capture confirm file". If it does not, then I check if the Access file Submaster_YYYYMMDD.mdb exists in the path ${datafrom}. If yes, then I read it and save subsYYYYMMDD.dta. The <code>exec()</code> part of <code>odbc load</code> is for running SQL syntax. Just to make sure that you appreciate the coolness of this: any SQL line that you could execute in Access, no matter how complicated, can be put between the <code>exec()</code> parentheses. Mine is simple -- I wrote the SQL commands in all caps for clarity -- but yours needn't be. You can also combine Stata locals with SQL syntax like I did.</p>
<p>I switch to the semicolon delimiter when it helps readability. It allows the line with SQL syntax to wrap around, and the listing of my `vars' local as one word per line. This, of course, is optional. The checks for the existence of either file are also optional. They keep my do-files from exiting with an error if I happen to run them on a day when either file does not exist -- either because the source file Submaster has not arrived yet, or because it hasn't been translated yet into Stata.</p>
]]></content:encoded>
			<wfw:commentRss>http://enoriver.net/index.php/2008/11/21/data-from-ms-access-to-stata/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Abstraction with macros</title>
		<link>http://enoriver.net/index.php/2008/09/28/abstraction-with-macros/</link>
		<comments>http://enoriver.net/index.php/2008/09/28/abstraction-with-macros/#comments</comments>
		<pubDate>Sun, 28 Sep 2008 23:18:03 +0000</pubDate>
		<dc:creator>Gabi Huiber</dc:creator>
				<category><![CDATA[Stata]]></category>
		<category><![CDATA[abstraction]]></category>
		<category><![CDATA[macros]]></category>

		<guid isPermaLink="false">http://enoriver.net/?p=145</guid>
		<description><![CDATA[When professional programmers talk about abstraction they mean writing code that is not too context-specific. The goal of abstraction is platform-independent code. That has become synonymous with "runs on both UNIX and Windows" but platform need not mean operating system. PHP, for example, has a database abstraction layer called PEAR::DB whose job is to allow [...]]]></description>
			<content:encoded><![CDATA[<p>When professional programmers talk about abstraction they mean writing code that is not too context-specific. The goal of abstraction is platform-independent code. That has become synonymous with "runs on both UNIX and Windows" but platform need not mean operating system. PHP, for example, has a database abstraction layer called PEAR::DB whose job is to allow your code to work with different database engines without any modification, because its commands are 'abstracted away' from any given engine. That is useful when your code must work with both MySQL and PostgreSQL, for example.</p>
<p>Stata can do something similar. What you aim to abstract from when writing do-files is not necessarily any given operating system, though you can do that too. Rather, abstraction should ensure that your code is not a literal translation of how you think about the job. Your most specific ideas at the beginning of a project are the most likely to change before the job is done. Writing flexible code that can accommodate such changes is a lot more convenient than cutting out and retyping big swaths of your masterpiece as you go along. Macros, local and global, can help.</p>
<p>One obvious use for macros is file path abstraction. You may well start a project with a simple structure -- such as "c:/my project/" with subfolders "data" and "code". But what if you move it to a new letter drive? What if along the way your data and code need to be re-organized in different sub-folders?</p>
<p>Declaring your file paths once, at the top of the do-file, as macros such as</p>
<p><code>local sourcefiles "c:/my project/data/source/"</code></p>
<p>will enable you to call your sourcefile in the same way throughout the rest of the do-file:</p>
<p><code>use "`sourcefiles'mysource", clear</code></p>
<p>The obvious advantage to this is that all the file path declarations are in one place, and each appears just once. Should you have to change any of them, you can do so very quickly and 100% reliably, and that is not a metaphor. You only need one change, in one place. That's 100%.</p>
<p>If you move from Windows to UNIX, you will simply change your macro's definition to something like this:</p>
<p><code>local sourcefiles "/usr/home/yourusername/my project/data/source/"</code></p>
<p>Everything else in your do-file can stay the same. That is true platform independence. File names, variable lists for sorting or merging, constants, all can be equally easily abstracted away with macros. You can even use macros to substitute inside commands, like so:</p>
<p><code>local thisvar_is_ready "thisvar&gt;0 &amp; thisvar!=."<br />
replace newvar=thatvar/thisvar if `thisvar_is_ready'<br />
</code><br />
Should your macros be global or local? The difference is one of scope. If you declare a global macro it stays live for the entire lifetime of your Stata instance, so global macros can be inadvertently carried over to do-files that they have nothing to do with. Local macros are local to the do-files where they are defined. They die when the execution of their home do-file stops, either at the end of the file or as the result of an error. For this reason the general advice is that you should not use a global macro when a local one will suffice.</p>
<p>But the upshot of that advice is not that the cautious Stata user will never use global macros. If you organize your work in hierarchical do-files that call each other, then it makes sense to declare all your macros as globals in one place -- the master do-file that calls all others.</p>
<p>I use a combination of global and local macros, as I judge the circumstances to warrant either type. I do not have a default preference. To ensure against carrying globals over to do-files where they do not belong, you could start your do-files with <code>capture macro drop _all</code>. That would be drastic, but all the more effective.</p>
]]></content:encoded>
			<wfw:commentRss>http://enoriver.net/index.php/2008/09/28/abstraction-with-macros/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
