Written and maintained by CASRAI Editorial Board
Last updated
graph box draws vertical box plots and graph hbox draws the identical chart rotated onto its side — every option covered here works the same way in both. over(groupvar) is the option that turns a single overall box plot into one box per category, and Stata marks points beyond the whiskers as outside values using diamond markers by default; marker() and its label sub-options are what let you attach an identifying label — a case ID, a subject number — to those specific outlier points.
This page covers the syntax specifically: what a Stata box plot actually draws, building grouped and nested box plots with over(), and labeling outlier observations so you can trace a flagged point back to a row in your dataset. For the underlying statistics — medians, quartiles, and how to report a distribution in prose — see CASRAI’s guide to descriptive statistics first if you need that background.
What a Stata box plot draws
Both commands draw the standard Tukey box plot: a box spanning the 25th to 75th percentile (the interquartile range, IQR) with a line at the median, whiskers extending to the most extreme non-outlying values, and separate markers — diamonds, by default — for any observation more than 1.5 times the IQR beyond the box edges. Stata calls these outside values, not “outliers,” in its own documentation, and that’s the term used in the marker()/nooutsides options below.
graph box score
graph hbox score
With one variable and no over(), you get a single box summarizing the whole sample. That’s rarely the useful case — most box plots exist specifically to compare a distribution across groups, which is what over() is for.
graph box vs. graph hbox: which one to use
The two commands take identical syntax; only the orientation differs. graph box puts categories along the horizontal axis with boxes running vertically — the familiar default. graph hbox puts categories along the vertical axis with boxes running horizontally.
Use graph hbox when category labels are long or there are more than five or six over() levels: rotated labels under vertical boxes become unreadable, but the same labels read cleanly down the left margin of a horizontal chart. Use graph box for short labels (a handful of treatment arms, yes/no, a few departments) where the vertical default is more familiar to readers.
graph box score, over(department)
graph hbox score, over(department)
Grouped box plots with over()
over(groupvar) is what turns one overall box into one box per category — it does almost all the real work in a Stata box plot, the same role it plays in graph bar:
graph box score, over(group)
You can stack multiple over() specifications to nest categories. The first over() becomes the outer grouping (shown spanning several boxes on the outer axis), and each subsequent over() nests inside it:
graph box score, over(treatment) over(site)
That draws one cluster of boxes per site, with treatment levels as the boxes inside each cluster. Order matters for readability — put the grouping variable with fewer categories on the outside so the labels stay legible.
You can also plot several separate y-variables side by side without over() at all — useful for comparing distributions of genuinely different variables rather than one variable split by group:
graph box pretest posttest
The two forms don’t combine cleanly by default: with multiple y-variables, add over() only if you also want each of those variables broken out further by group, which produces a busier chart than most guides recommend starting with.
Identifying outlier observations
By default a box plot shows you that a point is an outside value without telling you which observation it is. Stata’s marker() option is what attaches a label. Its syntax is marker(#, marker_options marker_label_options), where # numbers the plotted y-variable (almost always 1 when you’re plotting a single variable with over()) and the sub-options come from Stata’s general marker_options and marker_label_options — the same suboption families used on scatter and every other twoway plot. The one that matters here is mlabel(), which names the variable whose values should label each point:
graph box score, over(group) marker(1, mlabel(subject_id))
subject_id should be a variable that uniquely identifies each row — a case number, a participant ID — so that when you see a diamond sitting outside the whiskers, the label next to it tells you exactly which observation to go pull up with list or browse. mlabel() labels every plotted point on box 1, not only the outside values, so an uncluttered box plot with a handful of visible labels is the intended reading: the labels on points inside the whiskers are simply easy to ignore, and the ones that matter are attached to the diamonds sitting outside the box.
Two related options worth knowing:
nooutsidessuppresses outside-value markers entirely, drawing whiskers out to the full min/max instead — useful if you want a clean box-and-whisker for a presentation and plan to discuss outliers separately.marker_optionsinside the samemarker()call also control the outside-value marker’s symbol, size, and color (e.g.marker(1, msymbol(Oh) mcolor(red) mlabel(subject_id))), which is worth doing whenever the default diamonds are easy to miss against a busy chart.
If you’re plotting multiple y-variables (graph box pretest posttest) rather than one variable with over(), each variable is its own numbered box: marker(1, ...) styles/labels outside values for the first variable, marker(2, ...) for the second, and so on.
A worked example
graph box score, over(department, label(angle(45))) ///
marker(1, msymbol(Oh) mcolor(red) mlabel(subject_id)) ///
ytitle("Score") title("Score by Department")
This draws one box per department, angles the category labels 45 degrees so longer department names don’t overlap, styles outside-value markers as hollow red circles instead of the default diamonds, and labels each one with subject_id so a reviewer can trace any flagged point straight back to a specific row.
Frequently asked questions
What counts as an outside value in a Stata box plot?
Any observation more than 1.5 times the interquartile range beyond the nearer box edge (the 75th percentile plus 1.5×IQR on the high side, the 25th percentile minus 1.5×IQR on the low side) — the standard Tukey rule. Stata draws these as separate markers rather than extending the whisker to them.
Can I label only the outside values, not every point?
mlabel() inside marker() labels every point plotted on that box, including ones inside the whiskers — there’s no built-in switch that labels outside values only. In practice this is rarely a problem: labels on interior points sit close to a busy cluster of other marks and are easy to visually ignore, while labels on the isolated diamonds beyond the whiskers stand out on their own.
How is graph box different from graph bar for comparing groups?
graph bar plots a single summary statistic per group (typically the mean) and hides the underlying spread entirely. graph box plots the full distribution — median, IQR, range, and outside values — which is the better choice whenever skew or outliers could be masked by a mean-only bar chart. See CASRAI’s guide to bar charts in Stata for the graph bar syntax.
Does over() work the same way in graph box as in graph bar?
Yes — over() plays an identical role in both commands: it turns one overall plot into one plot per category, and stacking multiple over() options nests categories the same way in both.








