柱形竞赛图(Bar Chart Race)是一种动态的柱形图,它能非常直观地反应随着时间流逝数据的变化。下图是最终效果。
那么如何绘制呢?今天介绍一个开源库,就叫 bar_chart_race,使用这个库制作柱形竞赛图可以说非常简单了。
安装
安装 bar_chart_race 只需要通过 pip:
pip install bar_chart_race
bar_chart_race 使用 ffmpeg 生成 mp4 文件展示。所以还需要安装 ffmpeg:
conda install -c conda-forge ffmpeg
本示例使用 Mars 来预处理数据。安装 Mars 通过:
pip install pymars
准备数据
今天我们要绘制的是新冠确诊人数前十的国家的数据变化。我们使用数据集:地址,点击链接下载 CSV 文件。
In [1]: import mars.dataframe as md
In [2]: df = md.read_csv('countries-aggregated.csv')[['Date', 'Country', 'Confirmed']]
In [3]: df.execute()
Out[3]:
Date Country Confirmed
0 2020-01-22 Afghanistan 0
1 2020-01-22 Albania 0
2 2020-01-22 Algeria 0
3 2020-01-22 Andorra 0
4 2020-01-22 Angola 0
... ... ... ...
21239 2020-05-13 West Bank and Gaza 375
21240 2020-05-13 Western Sahara 6
21241 2020-05-13 Yemen 70
21242 2020-05-13 Zambia 446
21243 2020-05-13 Zimbabwe 37
接着我们确定柱状图上要显示哪些国家,这里我们计算出历史上总确诊人数排前十的国家显示。
In [4]: top_10 = df.groupby('Country').agg({'Confirmed': 'sum'}).sort_values(by='Confirmed', ascending=False)[:10]
In [5]: top_10.execute()
Out[5]:
Confirmed
Country
US 36901733
Italy 8940009
Spain 8862792
China 7778728
Germany 6730778
France 6391282
United Kingdom 5887815
Iran 4127613
Turkey 3888111
Russia 3450701
有了前10的国家,接着我们就需要从原始数据里过滤出来这些国家的数据。
In [6]: data_in_top_10 = df[df.Country.isin(top_10.index)]
In [7]: data_in_top_10.execute()
Out[7]:
Date Country Confirmed
36 2020-01-22 China 548
62 2020-01-22 France 0
66 2020-01-22 Germany 0
81 2020-01-22 Iran 0
85 2020-01-22 Italy 0
... ... ... ...
21196 2020-05-13 Russia 242271
21214 2020-05-13 Spain 228691
21229 2020-05-13 Turkey 143114
21230 2020-05-13 US 1390406
21234 2020-05-13 United Kingdom 230985
[1130 rows x 3 columns]
要绘图,bar_chart_race 接受一个横表,索引是时间,列标签是国家,里面的值就是每天的人数了。要做到这个效果只需要调用 DataFrame.pivot
做个列转行的操作即可,可惜 Mars 暂时还不支持 pivot,所以我们先转 pandas。
In [8]: # Mars 0.4 版本前(含 0.4.0rc1)通过 data_in_top_10.execute() 转成 pandas DataFrame
...: # 0.4 之后通过 to_pandas() 转
...: pivot_df = data_in_top_10.to_pandas().pivot(index='Date', columns='Country', values='Confirmed')
In [9]: pivot_df
Out[9]:
Country China France Germany Iran ... Spain Turkey US United Kingdom
Date ...
2020-01-22 548 0 0 0 ... 0 0 1 0
2020-01-23 643 0 0 0 ... 0 0 1 0
2020-01-24 920 2 0 0 ... 0 0 2 0
2020-01-25 1406 3 0 0 ... 0 0 2 0
2020-01-26 2075 3 0 0 ... 0 0 5 0
... ... ... ... ... ... ... ... ... ...
2020-05-09 83990 176782 171324 106220 ... 223578 137115 1309550 216525
2020-05-10 84010 177094 171879 107603 ... 224350 138657 1329260 220449
2020-05-11 84011 177547 172576 109286 ... 227436 139771 1347881 224332
2020-05-12 84018 178349 173171 110767 ... 228030 141475 1369376 227741
2020-05-13 84024 178184 174098 112725 ... 228691 143114 1390406 230985
[113 rows x 10 columns]
绘图
有了能用的数据,我们就正式开始绘图了。
In [10]: import bar_chart_race as bcr
Out[10]: bcr_html = bcr.bar_chart_race(df=pivot_df, filename=None,
steps_per_period=10, period_length=300,
title='COVID-19 Confirms by Country')
在 jupyter 里,可以直接显示竞争图。
In [11]: from IPython.display import HTML
Out[11]: HTML(bcr_html)
参考
Bar Chart Race:https://github.com/dexplo/bar_chart_race
Mars:https://github.com/mars-project/mars