|Getting nice time-of-day labels on a graph
|Nicholas J. Cox, Durham University, UK
If you are graphing data in Stata against time of day, one of your axes will show time. For all but the crudest exploratory graphics, good labeling of that axis is important. Tastes and conventions may vary, but many people like to show times for whole hours and in the form 12:00. Sometimes people like to distinguish times that are a.m. and times that are p.m. These may be called "nice" or "round" labels and go beyond what may be achieved by using format.
A companion FAQ addresses the question of date labels for daily dates: How can I get “nice” date labels on a graph?.
In what follows, we assume that time goes on the x axis. If you put time on the y axis, you just need to think in terms of the corresponding options; that is, for xlabel, read ylabel, and so forth. We also assume that time is measured on a scale running from 0 (usually midnight) to, or almost to, 24 (usually also midnight). If your time origin is not midnight, you will need to modify the methods here.
Let’s first suppose that you want labels for your variable timeofday to be in steps of three hours from midnight to midnight in the form 9:00 or 15:00. We type
Users of Stata 7 should not specify , valuelabel.
(When we type graph whatever, we naturally presume that you will replace that with something appropriate to your problem, such as graph twoway line temperature, or even line temperature.)
Now to explain the trickery: given the numlist 0(3)24, the value label for 0 is defined as "0:00", for 3 as "3:00", and so forth. Then these value labels are attached to our timeofday variable. Given a request to show those numbers as xlabels on a graph on which timeofday is shown on the x axis, Stata automatically uses attached value labels instead.
As you may know, the entity (here t) controlling the foreach loop is a local macro; inside the loop, its contents are referenced by `t'.
Next suppose that you want labels for your variable timeofday to be in a.m. or p.m. form, such as "9 a.m.". If only a few labels are required, defining them directly may be easiest:
Naturally, you may prefer some other convention for showing midnight or noon. There is no problem if the same label is used for different integers. If we wanted to do this in a loop, the boundary cases may need special care, so much so that typing out definitions one by one is attractive by comparison:
The functions mod() and cond() used here are explained in the [F] Functions Reference Manual. For further discussion, see Cox (2002).
Another solution is naturally just to supply labels on the fly:
That has some marked advantages and disadvantages. For a graph not to be repeated, it will be fast and direct. Moreover, if you want for some reason to show a label for a time such as 12:45 p.m., and time is measured in hours, then you can include 12.75 "12:45 p.m.", which you cannot do by value labels as 12.75 is not an integer. (12.75 is not a typo, as a moment’s thought will make clear.) On the other hand, typing such details repeatedly could be tedious, although there are other ways of avoiding that.