
Bar Chart Race, Explained - mbostock
https://observablehq.com/@d3/bar-chart-race-explained
======
mbostock
This tutorial was inspired by John Burn-Murdoch’s popular bar chart race from
earlier this year. There have been a couple thousand transitive forks of
John’s notebook!

Our hope with Observable is that reactive notebooks, as a form of literate
programming designed for tinkering, make code easier to understand and reuse.
Sharing code is already popular today, obviously, but we think helping people
better understand that code will foster creativity and innovation.

~~~
drewmate
Thanks, Mike. This is fantastic. I'm still just learning D3, but this type of
content (and Observable in general) has been immensely useful.

Where do you get ideas for your novel visualizations? Is there academic
literature on the psychology of presenting data like this, or are you just
dreaming up new things and adding features to D3 so you can do it? How do you
recommend making the jump from forking and adapting others' visualizations to
writing entirely new things from scratch?

~~~
mbostock
There are decades of academic literature on visualization and perception: IEEE
VIS (and InfoVis specifically), IEEE TVCG (Transactions on Visualization and
Computer Graphics), ACM SIGCHI, and lots more. If you’re interested in
learning about visualization I recommend starting with Tamara Munzner’s book,
Visualization Analysis & Design:

[https://www.cs.ubc.ca/~tmm/vadbook/](https://www.cs.ubc.ca/~tmm/vadbook/)

------
663e1b
What's the advantage of an animated bar chart compared to an area chart? I
personally think they're incredibly painful to look at but since I keep seeing
them pop up on reddit I'm sure there must be advantages I haven't thought of,
right?

~~~
mbostock
The alternatives I’d consider are a line chart and a bump chart.

[https://observablehq.com/@d3/multi-line-
chart](https://observablehq.com/@d3/multi-line-chart)
[https://observablehq.com/@jonsadka/scatterplot](https://observablehq.com/@jonsadka/scatterplot)

A bar chart race is in many ways “worse” than a static chart. The bar chart
race forces you to wait for the animation to finish, whereas a static chart
shows you everything simultaneously, and lets you look forward or backward in
time by just moving your eyes. This can be generalized to say that a well-
designed static chart is often better than an interactive or animated chart,
since in the static chart, everything is visible up-front.

But in the same way that a good visual hierarchy directs the reader’s
attention and simplifies a complex interface, bar chart races (and animations
more generally) are effective at getting the viewer to watch the race as it
originally played out, from start to finish. Time in the data is represented
as real time, so you’re only able to see a single moment in time.

So bar chart races are probably worse for most perceptual tasks, but as a
storytelling device, they are (seemingly) quite effective.

~~~
datasciencetext
How do you feel about line "races"? (ex.
[https://datasciencetexts.com/diversions/college_ranks_race.h...](https://datasciencetexts.com/diversions/college_ranks_race.html))

------
aao
Misses big interactive timeline for scrubbing and pausing, like a video.

~~~
mbostock
Yeah, that would be a nice addition. Chained transitions in D3 don’t currently
allow scrubbing, but this chart could be implemented using an explicit
timeline to support it (or maybe that’s something that could be added to
d3-transition).

------
rhplus
One property of these charts is that the data is normalized so that the
'winner' takes up 100% of the width for any given time-sample. This is useful
if you're trying to imply that the data is zero-sum, but not useful if you're
interested in understanding the changes for any one participant relative to
itself, or two participants relative to each other. I think in the example,
Apple's growth would be far more dramatic on a simple line chart.

~~~
mbostock
If you edit the line that sets the x.domain in the chart cell, you can see it
run with a fixed scale:

    
    
        x.domain([0, d3.max(keyframes, ([, data]) => d3.max(data, d => d.value))])

~~~
kyberias
Much better! Thank you.

------
uoaei
For a really simple improvement to the visuals, smooth the data with smoothing
splines before performing the race, then subsample/interpolate between your
data points for a smoother feel.

Every time I see the "ka-chunk" as yearly data is iterated through in lockstep
fashion, especially on a certain corner of the internet where "data is (or
should be) beautiful", I cringe.

~~~
mbostock
This could be likely done by editing the keyframes cell and using
d3.interpolateBasis instead of linear interpolation.

------
travisglines
These are amazingly useful for visualizing growth over periods of time.

Data Is Beautiful, one of my favorite short clip youtube channels does this
for all of their content:

[https://www.youtube.com/watch?v=ojARdKHKlI0](https://www.youtube.com/watch?v=ojARdKHKlI0)

