Tutorial¶
bar_chart_race offers a wide range of inputs to customize the animation. On this page, we'll cover many of the available options.
Data format¶
The data you choose to animate as a bar chart race must be provided in a specific format. The data must be within a pandas DataFrame containing 'wide' data where:
- Each row represents a single period of time
- Each column holds the value for a particular category
- The index contains the time component (optional)
Example data¶
The data below is an example of properly formatted data. It shows total deaths from COVID-19 for several countries by date. Each row represents a single day's worth of data. Each column represents a single country's deaths. The index contains the date. Any pandas DataFrame that conforms to this structure may be used to create a bar chart race.
Belgium | China | France | Germany | Iran | Italy | Netherlands | Spain | USA | United Kingdom | |
---|---|---|---|---|---|---|---|---|---|---|
date | ||||||||||
2020-04-08 | 2240 | 3337 | 10887 | 2349 | 3993 | 17669 | 2255 | 14792 | 14704 | 7111 |
2020-04-09 | 2523 | 3339 | 12228 | 2607 | 4110 | 18279 | 2403 | 15447 | 16553 | 7993 |
2020-04-10 | 3019 | 3340 | 13215 | 2767 | 4232 | 18849 | 2520 | 16081 | 18595 | 8974 |
2020-04-11 | 3346 | 3343 | 13851 | 2894 | 4357 | 19468 | 2653 | 16606 | 20471 | 9892 |
2020-04-12 | 3600 | 3343 | 14412 | 3022 | 4474 | 19899 | 2747 | 17209 | 22032 | 10629 |
Basic bar chart races¶
A single main function, bar_chart_race
, exists to create the animations. Calling it with the defaults returns the animation as an HTML string. The load_dataset
function is available to load sample DataFrames. If you are working within a Jupyter Notebook, it will automatically be embedded in the output as a video.
import bar_chart_race as bcr
df = bcr.load_dataset('covid19_tutorial')
bcr.bar_chart_race(df)
Vertical bars¶
By default, bars are horizontal. Use the orientation
parameter to switch it to vertical.
bcr.bar_chart_race(df, orientation='v')
Ascending bars¶
By default, the bars are plotted in descending order. Change the order by setting sort
to 'asc'
.
bcr.bar_chart_race(df, sort='asc')
Limit the number of bars¶
By default, all columns will be plotted. Use n_bars
to limit the number. When limiting bars, the smallest bar can drop off the plot.
bcr.bar_chart_race(df, n_bars=6)
Fix the order of the bars¶
By default, the bars will be ordered. Set fixed_order
to True
or to a specific list of column names to keep the order the same throughout.
bcr.bar_chart_race(df, fixed_order=['Iran', 'USA', 'Italy', 'Spain', 'Belgium'])
Fix the maximum value¶
By default, the maximum value of the axis moves with the largest bar. Set fixed_max
to True
to keep the maximum value equal to the largest overall value for all frames in the animation.
bcr.bar_chart_race(df, fixed_max=True)
Change animation smoothness¶
By default, 10 frames are used to step from one period to the next. Increase/decrease the smoothness of the animation with steps_per_period
.
bcr.bar_chart_race(df, steps_per_period=3)
You may also change the amount of time per period with period_length
, which is set to 500 milliseconds (half of a second) by default.
bcr.bar_chart_race(df, steps_per_period=20, period_length=200)
Interpolate the period¶
By default, the label for each frame changes after the entire period has been plotted. Linearly interpolate the value for the period with interpolate_period
. Below, every frame increase by 1 / 10 of a day (2 hours and 24 minutes).
bcr.bar_chart_race(df, interpolate_period=True)
Plot properties¶
Many properties of the plot can be set.
figsize
- sets the figure size using matplotlib figure inches (default:(6, 3.5)
)dpi
- controls the dots per square inch (default:144
)label_bars
- whether to label the bar values with text (default:True
)period_label
- dictionary of matplotlib text properties or boolean (default:True
)title
- title of plot
bcr.bar_chart_race(df, figsize=(5, 3), dpi=100, label_bars=False,
period_label={'x': .99, 'y': .1, 'ha': 'right', 'color': 'red'},
title='COVID-19 Deaths by Country')
Label sizes¶
Control the size of labels with bar_label_size
, tick_label_size
, and title_size
.
bcr.bar_chart_race(df, bar_label_size=4, tick_label_size=5,
title='COVID-19 Deaths by Country', title_size='smaller')
Setting font properties¶
Set font properties for all text objects with shared_fontdict
.
bcr.bar_chart_race(df, title='COVID-19 Deaths by Country',
shared_fontdict={'family': 'Helvetica', 'weight': 'bold',
'color': 'rebeccapurple'})
Customize bar properties¶
Set bar_kwargs
to a dictionary of keyword arguments forwarded to the matploblib bar
function to control bar properties.
bcr.bar_chart_race(df, bar_kwargs={'alpha': .2, 'ec': 'black', 'lw': 3})
Additional features¶
There are several more additional features to customize the animation.
Formatting the period¶
Format the label of the period by setting period_fmt
to a string with either a date directive or a new-style formatted string.
bcr.bar_chart_race(df, period_fmt='%b %-d, %Y')
Use numbers for the index instead of dates¶
It's not necessary to have dates or times in the index of the DataFrame. Below, the index is dropped, which replaces it with integers beginning at 0. These are then interpolated and formatted.
bcr.bar_chart_race(df.reset_index(drop=True), interpolate_period=True,
period_fmt='Index value - {x:.2f}')
Add text summarizing the entire period¶
Define a function that accepts two arguments, the values and ranks of the current period of data, and returns
a dictionary that will be passed to the matplotlib text
function.
def summary(values, ranks):
total_deaths = int(round(values.sum(), -2))
s = f'Total Deaths - {total_deaths:,.0f}'
return {'x': .99, 'y': .05, 's': s, 'ha': 'right', 'size': 8}
bcr.bar_chart_race(df, period_summary_func=summary)
Add a perpendicular bar¶
Add a single bar perpendicular to the main bars by defining a function that accepts two arguments, the values and ranks of the current period of data, and returns a single number, the position of the bar. You can use string names of aggregation functions that pandas understands.
bcr.bar_chart_race(df, perpendicular_bar_func='mean')
An example with a user-defined function:
def func(values, ranks):
return values.quantile(.9)
bcr.bar_chart_race(df, perpendicular_bar_func=func)
Bar colors¶
By default, the 'dark12'
colormap is used, with 12 unique colors. This is a qualitative color map containing every other color from the 'dark24' colormap originally found from the plotly express documentation. All matplotlib and plotly colormaps are available by name. The entire 'dark24'
colormap will be used by default when your DataFrame contains more than 12 columns.
bcr.bar_chart_race(df, cmap='antique')
Reduce color repetition¶
It is possible that some colors repeat in your animation, even if there are more colors in the colormap than bars in the animation. This will only happen if you set the n_bars
parameter, as colors are assigned to each column upon. You'll get a warning advising you to set
filter_column_colors
to True
, which will only assign colors to those bars appearing in the animation.
The following example uses the Accent colormap which has 8 unique colors. The animation is set to have a maximum of 7 bars, but there are still repeating colors.
bcr.bar_chart_race(df, cmap='accent', n_bars=7)
UserWarning
Some of your columns never make an appearance in the animation. To reduce color repetition, set filter_column_colors
to True
Setting filter_column_colors
to True
will reduce the likelihood of repeating colors, but will still happen if the total number of unique bars is more than the number of colors in the colormap.
bcr.bar_chart_race(df, cmap='accent', n_bars=7, filter_column_colors=True)
Using your own figure¶
If you want to highly customize the animation, set the fig
parameter to a previously created figure. This figure must have at aleast one matplotlib axes created within it.
fig, ax = plt.subplots(figsize=(5, 2), dpi=120)
ax.set_facecolor((0, 0, 1, .3))
bcr.bar_chart_race(df, n_bars=3, fig=fig)
With subplots¶
It's possible to add an animation to a matplotlib figure containing multiple subplots. The first subplot will be used for the animation.
from matplotlib import dates
fig, ax_array = plt.subplots(2, 2, figsize=(8, 4), dpi=120, tight_layout=True)
ax1, ax2, ax3, ax4 = ax_array.flatten()
fig.suptitle('Animation in First Axes', y=1)
ax2.plot(df)
ax2.xaxis.set_major_locator(dates.DayLocator([3, 7, 12]))
ax3.bar(df.index, df.median(axis=1))
ax3.xaxis.set_major_locator(dates.DayLocator([3, 7, 12]))
ax4.pie(df.iloc[-1], radius=1.5, labels=df.columns)
bcr.bar_chart_race(df, n_bars=3, fig=fig)
Saving the animation¶
Default returned values¶
By default, the video will be embedded into your Jupyter Notebook. If you are not in a Jupyter Notebook, but have IPython installed, an HTML
object will be returned. Retrieve the underlying HTML with the data
attribute.
html = bcr.bar_chart_race(df)
html.data # very long string of HTML
If you do not have IPython installed, then a string of HTML will be returned directly.
Saving to disk¶
In order to save the animation to disk, use a string of the file name of where you'd like to save as the second argument. You'll need to install ffmpeg first in order to save the animation. Once installed, you'll be able to save the animation as a wide variety of formats (mp4, m4v, mov, etc...). To save the animation as a gif, install ImageMagick.
bcr.bar_chart_race(df, 'docs/videos/covid19.mp4', figsize=(5, 3))
Matplotlib writer¶
To customize the animation, set the writer
parameter to a matplotlib MovieWriter
object instance.