help framed_bar

Title

framed_bar -- Framed bar charts

Syntax

Syntax 1:

framed_bar
varname
[if] [in]
[weight]
,
over(groupvar)
[
statistical_options
bar_chart_options
annotation_options
twoway_options
display_options
]

Syntax 2:

framed_bar
varlist
[if] [in]
[weight]
[
,
statistical_options
bar_chart_options
annotation_options
twoway_options
display_options
]

fweights, aweights, pweights and iweights are allowed: see weight.

Description

framed_bar draws framed bar charts showing summary statistics for
one or more numeric variables. Frames comparing bars with limiting values
can work to simplify, by making an obvious complement tacit rather than
explicit, and to clarify, by making near extremes evident.

Recall that when you are drinking from a glass, your glass can be easily
judged as (nearly) full, (nearly) empty, or in between. The glass analogy
works better with vertical bars.

It is best explained statistically by a leading application. Suppose we have a
binary (Boolean, dichotomous, dummy, indicator, logical, one-hot,
quantal, zero-one) variable conventionally coded 0 or 1. A common jargon
is that the state coded 0 is dubbed failure and the state coded 1
is dubbed success; sometimes these terms are evocative and
otherwise they are just terms of art.

A common graphic for such data is a stacked bar chart showing the
proportions of whatever is coded 0 and whatever is coded 1. However,
missing values aside, those two proportions necessarily add to 1. Hence
an alternative graphic is just a bar chart showing the proportion of
successes within a frame of height or length 1. The empty space
corresponds to the proportion of failures. Equivalently, such a bar
chart plots the mean or means of one or more sets of binary values, as a
mean of such a (0, 1) variable is just the proportion of successes.

Variations on this design are offered by default or may be achieved by
options. Headline possibilities include

Any single summary statistic offered by collapse may be chosen
rather than means.

Annotation by default shows the statistics (say means) concerned as a
numeric text display.

Annotation may be shown optionally of sample sizes as a numeric text
display.

Values shown may on the fly be replaced according to a specified
calculation.

Frames may be suppressed. A frame may be irrelevant to your data or your
purpose, but you may like the design otherwise.

Quick start

. set scheme stcolor

. sysuse auto, clear

% foreign by repair record: frames at 100%

. framed_bar foreign, over(rep78) calc(100*@) frame(100) barlabel(mlabf(%2.0f)) yla(none) ytitle(% foreign)

. sysuse nlsw88, clear

. local yla yla(0(20)100)

. local xla xla(0(20)100)

. local blab mlabs(large) mlabf(%2.1f)

% for various indicators: frames at 100%

. framed_bar never married collgrad smsa, calc(100*@) frame(100) barlabel(`blab') count(size(medlarge)) `yla' ytitle(Percent)

All possible observations, or casewise deletion: sample sizes shown

. framed_bar union married collgrad smsa, calc(100*@) allobs sort frame(100) barlabel(`blab') count(mlabs(medlarge)) `yla' ytitle(Percent)

Number of missing values (by subtraction from sample size)

. framed_bar grade industry occupation union hours tenure, stat(count) calc(`=_N' - @) allobs sort frame(0) horizontal barlabel(mlabc(black) mlabs(medlarge) mlabf(%1.0f)) xsc(off) subtitle(Missing values)

Proportion of college graduates by race and union worker

. framed_bar collgrad, over(union) by(race, row(1)) barlabel(mlabf(%04.3f)) ytitle(Proportion of college graduates) yla(0 "0" 1 "1" 0.2(0.2)0.8, format(%02.1f))

Options

over() specifies a numeric or string variable groupvar. A
separate bar will be shown for each distinct value of groupvar. It
is a required option with syntax 1 but not allowed otherwise. Missing
values of groupvar are ignored.

Statistical options

statistic() specifies any single statistical summary to be shown.
The default is to show means. Any statistic produced by collapse
may be selected.

calculator() specifies a calculation to be applied on the fly
using an expression containing @ to indicate the initial results.
calc(100 * @) for example specifies that percents rather than
proportions be shown if the application is to means of indicator
variables. calc(25.4 * @) converts inches to mm.
calc(1 - @) would mean that 1 - p is to be shown rather than
p. This option has no effect on any axis title.

allobs applies if you wish to summarize occurrence of missing
values and/or to work with several variables that are being plotted
together. By default, calculations are only made with observations that
have non-missing values for all variables specified. This option
overrides that default selection: hence observations with missing values may be included
for one or more variables, while for several variables which
observations with non-missing values are used will be determined
separately for each variable. In other jargon, this option triggers
casewise deletion, not listwise deletion or complete case analysis.
As a convenience for people familiar with that term, cw is a
synonym for allobs.

sort specifies that results are be shown in increasing order, so
increasing from left to right or from bottom to top across the graphic.
If specified together with descending, results will be shown
decreasing from left to right or from bottom to top. If specified together
with the subset() option, sorting will be based on order in the
specified subset. See also myaxis (Cox 2021),

Bar chart options

frame() specifies the height of the frame. Note that
frame(0) or frame(.) wpuld suppress any (visible) frame. The
default is frame(1) and so geared to showing means of indicator
variables.

frameopts() are options of twoway bar tuning the rendering
of frames. Defaults are fcolor(none) pstyle(p2) and as explained
below barwidth(0.8).

base() specifies the position of the base of bars and defaults to
0. It seems unlikely that you should prefer another value, but it may be
specified.

barwidth() specifies the width of bars and defaults to 0.8.

horizontal specifies horizontal bars. The default is vertical
bars.

Annotation options

As a general rule, these annotation options are not especially smart in
use of graph space. The displays shown may encroach on space used by
axes or their details. You may wish to use axis scale options
such as xscale() or yscale() to extend the space available.
See the Examples to get the idea.

barlabel() tunes display of the bar labels that appear by default
at the top of vertical bars or at the right of horizontal bars showing
the numeric magnitudes concerned.

As a special case, barlabel(none) suppresses this display.

Otherwise, the defaults include pstyle(p1) and mlabpos() of
12 for vertical bars and 3 for horizontal bars. In particular, if you
are displaying integers, you may wish to specify mlabformat(%1.0f).
In general, see marker label options for other possibilities.

countlabel or countlabel() specifies that the number of observations
used be displayed at the bottom of vertical bars or at the left of
horizontal bars. This option may specify marker label options or
other options affecting such display. pstyle(p1) is a default for
this display.

Exceptionally however, with syntax 2 and if you not specify the
allobs option, then the number of observations is necessarily a
constant and will be displayed using note(). Options that apply
to note() may be used to tune the display.

countlabelprefix() controls text before the displayed count.
The default is "n = ". As a special case, countlabelprefix(none)
removes that text.

countlabelsuffix() controls text after the displayed count.
The default is to show nothing.

twoway options

twoway_options are other options of twoway. Good examples
would be by(), name() or saving(). Note that ticks
on the "categorical" axis (horizontal for vertical bars; vertical for
horizontal bars) have been rendered invisible using the sub-option
tlc(none), See also Cox and Wiggins (2019) for more on tricks
with ticks.

Note that by(, total) and by(, missing) are not supported.

display options

list requests a listing of main output.

format() specifies a numeric display format for display of summary statistics.

Remarks

Why is this offered as a new command? There are for me as author three
main reasons.

graph bar, graph hbar and for that matter graph dot
offer charts showing summary statistics for groups and/or variables.
twoway bar allows frames to be drawn as empty bars on which other
bars can be superimposed. I often want to see both in combination.

I often want annotation showing numbers of observations used.

I often want to work around various small defaults with graph bar
and its kin, such as over-willing use of legends and axis ticks and
neglect of variable labels.

Users of this command should note that it is based on twoway, not
graph bar, graph hbar or graph dot.

On frames:

See especially Cleveland and McGill (1984) or Cleveland (1985; examples
on pp.209, 222, 287) or Cleveland (1994; example on p.241) or Munzer
(2015, pp.112-113) for direct explanation of the idea of framed rectangles.

See Dunn (1987, 1988), Monmonier (1993, pp.64-65, 184-185, 284)
and Kosslyn (1994, pp.248-249, 290) or Kosslyn (2006,
pp.235-238) for cartographical applications.

See Wilkinson (1999, 2005), Wild and Seber (2000), Favillae (2008), Keen
(2010, 2018), or Wexler (2021, pp.186, 188-189, 191) for examples
in terms of thermometer glyphs, plots or charts. The main idea is much
older, although there is not a sharp division between showing a framed
rectangle and showing a stacked or divided bar chart with (usually) two
complementary fractions. Brinton (1939, pp.51, 103, 200) gave various
examples; his earliest source is Emeny (1934, pp.17, 169). Karsten
(1923, p.122) and Mudgett (1930, p.81) gave other clear examples. For
fairly literal examples of the thermometer idea, see Haskell (1919,
p.106), Haskell (1922, p.215) and Karsten (1923, p.130). The same idea
is standard to those accustomed to thinking in terms of mosaic plots or
their variants under any other name, in which each axis shows a
probability scale: see e.g. Unwin et al. (2006) or Unwin (2015).

Frames are supported in tabplot (Cox 2016, but in
the 2020 update).

For an example of implicit frames, see Bawden (2024).

For alternative displays of sets of indicator variables, see
commands discussed by Cox and Morris (2024).

Examples

As indicated, these examples were developed using the stcolor
scheme. If you need or prefer to use another scheme, then some commands
may need tweaking. In particular, you may need to extend axes to
accommodate added text comfortably.

. set scheme stcolor

. sysuse auto, clear

First, compare stacked bars for a binary outcome:

. graph hbar, over(foreign) over(rep78) asyvars stack percent ytitle(percent) l1title(Repair record 1978) name(GH, replace)

. * ssc inst catplot

. catplot, over(foreign) over(rep78) percent(rep78) asyvars stack l1title(Repair record) name(CAT, replace)

Now turn to framed_bar:

. framed_bar foreign, over(rep78) calc(100*@) frame(100) barlabel(mlabf(%2.0f)) yla(none) ytitle(% foreign) name(FB1, replace)

. framed_bar foreign, over(rep78) calc(100*@) frame(0) barlabel(mlabf(%2.0f) mlabs(medlarge)) yla(none) ytitle(% foreign) name(FB2, replace)

. sysuse nlsw88, clear

. local yla yla(0 "0" 1 "1" 0.2(0.2)0.8, format(%02.1f))

. local xla xla(0 "0" 1 "1" 0.2(0.2)0.8, format(%02.1f))

. framed_bar collgrad, over(race) barlabel(mlabf(%04.3f) mlabs(large)) `yla' ytitle(Proportion of college graduates) name(FB3, replace)

. framed_bar collgrad, over(race) barlabel(mlabf(%04.3f) mlabs(large)) count(mlabs(medlarge)) `yla' ytitle(Proportion of college graduates) name(FB4, replace)

. framed_bar collgrad, over(race) barlabel(mlabf(%04.3f) mlabs(large)) count(mlabs(medlarge)) horizontal `xla' xsc(r(-0.16 .)) xtitle(Proportion of college graduates) ysc(reverse) name(FB5, replace)

. local yla yla(0(20)100)

. local xla xla(0(20)100)

. local blab mlabs(large) mlabf(%2.1f)

. framed_bar never married collgrad smsa, calc(100*@) frame(100) barlabel(`blab') count(size(medlarge)) `yla' ytitle(Percent) name(FB6, replace)

. framed_bar union married collgrad smsa, calc(100*@) frame(100) horizontal barlabel(`blab') count(size(medlarge)) `xla' xtitle(Percent) name(FB7, replace)

. framed_bar union married collgrad smsa, calc(100*@) allobs frame(100) barlabel(`blab') count(mlabs(medlarge)) horizontal xsc(r(-20 .)) `xla' xtitle(Percent) name(FB8, replace)

. framed_bar union married collgrad smsa, calc(100*@) allobs sort frame(100) barlabel(`blab') count(mlabs(medlarge)) `yla' ytitle(Percent) name(FB9, replace)

. framed_bar grade industry occupation union hours tenure, stat(count) calc(`=_N' - @) allobs sort frame(0) horizontal barlabel(mlabc(black) mlabs(medlarge) mlabf(%1.0f)) xsc(off) subtitle(Missing values) name(FB10, replace)

. framed_bar collgrad, over(union) by(race, row(1)) barlabel(mlabf(%04.3f)) ytitle(Proportion of college graduates) yla(0 "0" 1 "1" 0.2(0.2)0.8, format(%02.1f)) name(FB11, replace)

. framed_bar collgrad, over(union) by(race, row(1)) horizontal barlabel(mlabf(%04.3f)) ytitle(Proportion of college graduates) xla(0 "0" 1 "1" 0.2(0.2)0.8, format(%02.1f)) name(FB12, replace)

. framed_bar collgrad union, by(race, row(1)) barlabel(mlabf(%04.3f)) name(FB13, replace)

. framed_bar collgrad union, by(race, row(1)) horizontal barlabel(mlabf(%04.3f)) name(FB14, replace)

. framed_bar collgrad union smsa married, by(race, row(1)) frame(0) horizontal barlabel(mlabf(%04.3f)) recast(dropline) name(FB15, replace)

. framed_bar collgrad union smsa married, by(race, row(1)) sort subset(race==2) frame(0) horizontal barlabel(mlabf(%04.3f)) recast(dropline) xla(none) name(FB16, replace)

Author

Nicholas J. Cox, Durham University

n.j.cox@durham.ac.uk

Acknowledgments

Although frames as a graphic device are at least a century old, my understanding owes most to the work of
William S. Cleveland. Encouragement to use frames in tabplot arose from comments from William Huber and
Jeff Laux. The initial stimulus for this command was in a Statalist thread by Jonathan Afilalo. Encouraging comments came from Tim Morris. Comments from Marc Kaulisch led to extra options for count label display.

References

Bawden, A. 2024.
Sharp drop in condom use putting young people's health at risk, WHO report says.
The Guardian 30 August, p.14.
https://www.theguardian.com/society/article/2024/aug/29/young-peoples-health-at-risk-from-fall-in-condom-use-warns-who

Brinton, W.C. 1939.
Graphic Presentation.
New York: Brinton Associates.

Cleveland, W.S. 1985.
The Elements of Graphing Data.
Monterey, CA: Wadsworth.

Cleveland, W.S. 1994.
The Elements of Graphing Data.
Summit, NJ: Hobart Press.

Cleveland, W.S. and R. McGill. 1984.
Graphical perception: theory, experimentation, and application to the
development of graphical methods.
Journal of the American Statistical Association
79: 531-554.

Cox, N.J. 2016.
Speaking Stata: Multiple bar charts in table form.
Stata Journal 16: 491-510.
Updates 17: 779; 20: 757-758; 22: 467.

Cox, N.J. 2021.
Speaking Stata: Ordering or ranking groups of observations.
Stata Journal 21: 818-837.

Cox, N.J. and T.P. Morris. 2024.
Speaking Stata: The joy of sets: Graphical alternatives to Euler and Venn diagrams.
Stata Journal 24: 329-361.

Cox, N.J. and V. Wiggins. 2019.
Stata tip 132: Tiny tricks and tips on ticks.
Stata Journal 19: 741-747.

Dunn, R. 1987.
Variable-width framed rectangle charts for statistical mapping.
American Statistician 41: 153-156.

Dunn, R. 1988.
Framed rectangle charts or statistical maps with shading: An experiment in graphical perception.
American Statistician 42: 123-129.

Emeny, B. 1934.
The Strategy of Raw Materials: A Study of America in Peace and War.
New York: Macmillan.

Favillae. 2008.
Thermometer plots in R.
https://favillae.blogspot.com/2008/11/thermometer-plots-in-r.html

Haskell, A.C. 1919.
How to Make and Use Graphic Charts.
New York: Codex Book Company.

Haskell, A.C. 1922.
Graphic Charts in Business: How to Make and Use Them.
New York: Codex Book Company.

Karsten, K.G. 1923.
Charts and Graphs: An Introduction to Graphic Methods in the Control and Analysis of Statistics.
New York: Prentice-Hall.

Keen, K. J. 2010 (second edition 2018).
Graphics for Statistics and Data Analysis with R.
Boca Raton, FL: CRC Press.

Kosslyn, S.M. 1994.
Elements of Graph Design.
New York: W.H. Freeman.

Kosslyn, S.M. 2006.
Graph Design for the Eye and Mind.
New York: Oxford University Press.

Monmonier, M. 1993.
Mapping It Out: Expository Cartography for the Humanities and Social Sciences.
Chicago: University of Chicago Press.

Mudgett, B.D. 1930.
Statistical Tables and Graphs.
Boston, MA: Houghton Mifflin.

Munzner, T. 2015.
Visualization Analysis and Design.
Boca Raton, FL: CRC Press..

Unwin, A. 2015.
Graphical Data Analysis with R.
Boca Raton, FL: Taylor & Francis.

Unwin, A., M. Theus, and H. Hofmann. 2006.
Graphics of Large Datasets: Visualizing a Million.
New York: Springer.

Wexler, S. 2021.
The Big Picture: How to Use Data Visualizations to Make Better Decisions-Faster. New York: McGraw Hill.

Wild, C.J. and G.A.F. Seber. 2000.
Chance Encounters: A First Course in Data Analysis and Inference.
New York: John Wiley.

Wilkinson, L. 1999.
The Grammar of Graphics.
New York: Springer.

Wilkinson, L. 2005.
The Grammar of Graphics. 2nd ed.
New York: Springer.

Also see

twoway bar

myaxis (Stata Journal) (if installed)

tabplot (Stata Journal) (if installed)

upsetplot, vennbar (Stata Journal) (if installed)