Abstract

1 The problem: Messy category labels with graph bar
Stata does not have the concept of a categorical variable, but statistical people do, as shown by many book titles alone (for example, Fienberg [1980]; Lloyd [1999]; Simonoff [2003]; Tutz [2012]; Agresti [2013]; Long and Freese [2014]). The categories of such variables are distinct and often, but not necessarily, few in number. Examples are differing disease condition, employment status, or land cover type. A categorical variable in Stata can be stored as string; as numeric with value labels; or sometimes as just numeric, as when the number of cars or cats or children in households is just a discrete count that you want to treat as categorical.
The main focus of
The general problem addressed in this tip is that you are using
The y axis is as usual the vertical axis showing outcome values or means or counts or whatever else the graph shows. One good reason for that idiosyncrasy is that typing
The example in this thread of a bar chart for time series raises just about all the generic issues that arise commonly. It also raises some specific issues for time series that are frequent.
The immediate stimulus for this tip was a thread on Statalist,
which started on 24 July 2020. R. Allan Reese in particular made one suggestion incorporated here.
Let’s dive in and consider the use of a bar chart for two time series from the Grunfeld dataset bundled with your version of Stata. Bars side by side for two or more variables are often wanted and one of the attractions of
We are setting on one side any discussion of whether some other kind of graph, such as a line chart, would be better; or of whether it is a good idea to juxtapose two series that may not have even the same units of measurement.
Time in the Grunfeld dataset is each year from 1935 to 1954, but
To set yet other details out of the way, let’s say that we have decided in advance what bar colors we want and where the legend should go. In practice, a script for your own data may go through several iterations as you play with possibilities and discover small points to be resolved.

The time labels overlap. What to do?
Figure 1 is evidently poor, even though there are only 20 distinct years here. As you know, very many time series include far more times, but 20 is enough to cause a mess.
The thinking of
2 Possible solutions
2.1 Possible solution: Use graph hbar instead
Very often, the answer is simply to go horizontal by using
When this is the answer, good, and you bail out here.
For time series, this is not usually an acceptable answer. There is a strong convention across many fields that time belongs on the horizontal axis. Put your time variable on a vertical axis, and someone reviewing your work is likely to query that directly.
2.2 Possible solution: Use shorter text labels through value labels
You could assign value labels, such as
Typing out definitions for 20 value labels (to say nothing of many more, as would be needed for longer series) is less fun than writing a loop to write code for your later
The initial statement
deserves comment. Thereby, I blank out any contents of the local macro call that exist (equivalently, I delete the macro if it exists). That way, I will not get bitten because of whatever is left behind in the macro from any previous code. This device will be used repeatedly in what follows. Here the macro does not exist at the outset, but explicitly blanking it out is suggested as good style.

Insisting on shorter text labels (through value labels) removes the overlap. There are still questions: Do you want all those labels? Would this work with more distinct times?
Figure 2 is much better. You might want to stop here. But to spell out what is key: What we did was set up value labels such as
So far so good, but even for this example you might think “too many labels!”. Your real data might be a time series with many more values, and if so, you really would think that.
Value labels that are just
Note that although you can set some of your value labels to spaces or even more exotic characters such as
2.3 Possible solution: Use relabel()
The help for

Every other year label is blanked out. Strictly, you are seeing spaces as value labels for even years, but the effect is identical.
Figure 3 shows the effect of showing fewer text labels.
If the
A guess suggests, and experiment confirms, that for these data we have enough space to show 1935 1937 to 1953. Let’s clear the value labels out of the way and just show spaces instead of the even-numbered years.

Showing every other year works well for these data. Strictly, the text for omitted years is a space, but the effect is as desired.
Figure 4 is in my view better than any previous figure. The same amount of text is shown on the x axis, but few readers should have difficulty imagining the omitted labels. There is not the puzzle of decoding 35 to 53 as years in their century.
2.4 Possible solution: Use twoway bar instead
You may be thinking that all of this is more messing around than you want for a very mundane problem. Is not there a simpler solution? For time series, there is, and it hinges on switching to
For bars side by side, you need to work a little at defining offset variables (Cui 2007). For two bars, we move one bar to the left and one bar to the right. We do need some small arithmetic to determine not just bar offsets but also good bar widths (which default to 1). Although we do not spell out any details, you could set up three or more bars, with the usual trade-off between the information gain in encoding several variables and the difficulty of decoding the several bars easily and effectively.
Now, your horizontal axis labels really are controllable simply and directly by the option

Just use
Figure 5 plots one series of bars against one year variable offset left and the other series against one year variable offset right. The upshot is that
Many users start with
2.5 Edit the value labels or string values
It is not relevant here, but often the solution is to slim down the existing value labels or string values. It can be prudent to save the original versions in case you want to go back for some later purpose.
