上一篇咱們對數據進行了從新佈局,佈局後的數據結構方便咱們進行柱狀圖可視化以及彈道分析。html
今天咱們來學習使用該數據集執着更酷炫的動態排名視頻。python
先看效果:api
一如既往,直奔代碼。數據源就是咱們一直分析的COVID19 data 數據,能夠去kaggle 下載。數組
導入咱們所需的庫,相比於以前的文章,咱們本次分析會用到animation模塊,重點是裏面會提供FuncAnimation 類,幫助咱們實現動態圖。bash
# coding: utf-8
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.animation as animation
from datetime import datetime, timedelta
import numpy as np
複製代碼
pandas 讀取數據,這是每篇分析的第一步操做。 簡單處理數據,採用groupby 函數將一些國家的各個省份信息合併成該國家的總和。 前一篇文章有詳細介紹,此處再也不說明。數據結構
# read data
covid19_data_file = 'data/COVID_19_data.csv'
covid19_data_df = pd.read_csv(covid19_data_file)
# handle the countries data
df_country = covid19_data_df.groupby(
['ObservationDate', 'Country/Region']).sum()
df_country.reset_index(inplace=True)
複製代碼
你們都知道,視頻就是一堆堆圖像(或者稱爲幀 frame)在時間軸上連續起來造成的。因此咱們的思路也很簡單,製做一個畫面,改變畫面的內容,重複製做這個畫面。ide
matplotlib 已經有這個類:FuncAnimation,它用來重複調用一個函數進行畫圖。咱們來研究一下它的主要參數,更詳細的請參考官方文檔。函數
class matplotlib.animation.FuncAnimation(fig, func, frames=None, init_func=None, fargs=None, save_count=None, *, cache_frame_data=True, **kwargs)[source]¶
複製代碼
其中主要的參數:佈局
爲了調用這個函數,咱們須要準備好各個參數。post
fig, ax = plt.subplots(figsize=(15, 8))
start_date = datetime(2020, 1, 22)
end_date = datetime(2020, 5, 13)
dates_delta = (end_date - start_date).days
複製代碼
先上代碼,再作解釋。
def mini_bar_chart_frame(
delta,
df=None,
start_date=None,
date_col=None,
cat_col=None,
observe_col=None,
top_k=10,
ax=None):
if start_date is None:
start_date = datetime(2020, 2, 22)
date_show = timedelta(days=delta) + start_date
date_str = date_show.strftime('%m/%d/%Y')
top_k_df = df[df[date_col].eq(date_str)].sort_values(
by=observe_col, ascending=False).head(top_k)
ax.clear()
# plot horizon bar
ax.barh(
top_k_df[cat_col],
top_k_df[observe_col],
log=False)
ax.invert_yaxis() # to make the biggest in the top
#dx = np.log(top_k_df[observe_col].max()) / 200
for i, (value, name) in enumerate(
zip(top_k_df[observe_col], top_k_df[cat_col])):
ax.text(
value - 20,
i,
name,
size=10,
weight=600,
ha='right',
va='center')
ax.text(
value + 0.1,
i,
f'{value:,.0f}',
size=10,
ha='left',
va='center')
ax.text(
1,
0.1,
date_str,
transform=ax.transAxes,
size=40,
ha='right',
weight=800)
ax.set_yticks([]) # we have label on the top of bar
複製代碼
代碼中咱們主要實現一下內容:
函數準備好了,下面咱們就將函數的對應的參數傳遞給FuncAnimation。
fargs = (df_country,
start_date,
'ObservationDate',
'Country/Region',
'Confirmed',
10,
ax)
animator = animation.FuncAnimation(
fig,
mini_bar_chart_frame,
frames=dates_delta,
fargs=fargs,
interval=1000,
repeat=False)
複製代碼
咱們也可使用如下代碼將其保存爲本地mp4格式。
writer = animation.writers['ffmpeg']
writer = writer(fps=1)
animator.save('mini_covid_bar_race.mp4', writer=writer)
複製代碼
咱們看一下上述代碼的輸出結果,這裏我將視頻轉成gif以作演示。基本效果已經成型,應該算是很經典的動態排名了。
給柱狀圖添加顏色,應該很好處理。barh 函數帶有color 參數,這裏僅僅須要注意傳入的顏色須要是類數組的格式。 小技巧:
color_dict = {'Mainland China': '#e63946',
'US': '#ff006e',
'Italy': '#02c39a',
'Span': '#f4a261',
'UK': '#3a86ff',
'Germany': '#370617',
'France': '#3a86ff',
'Japan': '#d8e2dc',
'Iran': '#fec89a',
'Russia': '#dc2f02'}
# barh 中的color 參數爲:
# color=[
# color_dict.get(
# x,
# "#f8edeb") for x in top_k_df[cat_col]],
複製代碼
這裏我添加了一些文字來給視頻作註釋。好比3月15日,中國捐給西班牙50萬個口罩。
之因此用英文,是由於最初這個視頻是我放在facebook上給老外看的。
第二個緣由,是由於中文須要一些字體支持。
實現動態文字添加的思路很簡單,就是ax.text 函數。實現方法相似於咱們的國家標籤以及確診數的標籤。
timeline_event = {
'01/30/2020': 'WuHan declared lockdown.',
'01/31/2020': 'Italian suspended all flights from China',
'02/02/2020': 'Trump restricts on any foreigners from entering the U.S',
'03/13/2020': 'China sent medical supplies to Italy',
'03/15/2020': 'China donated 500,000 facemasks to Spain',
'03/19/2020': 'USA suspended visa services worldwide.',
'05/12/2020': 'America first(LOL).'
}
複製代碼
xkcd 是啥? 只不過一個漫畫名稱而已,很差發音,也不是縮寫。對於matplotlib 來講,xkcd 就指的相似於漫畫的的效果。通俗講就是「線條抖啊抖啊抖~~~~」 代碼很簡單就一行:
with plt.xkcd():
把全部plt相關的代碼放在這個with 裏面
複製代碼
除了添加顏色,動態文字以及「抖啊抖」的效果,咱們還作了一些細節處理,好比調整字體顏色,字號等小細節。
def xkcd_bar_chart_frame(
delta,
df=None,
start_date=None,
date_col=None,
cat_col=None,
observe_col=None,
top_k=10,
color_dict=None,
ax=None):
if start_date is None:
start_date = datetime(2020, 2, 22)
date_show = timedelta(days=delta) + start_date
date_str = date_show.strftime('%m/%d/%Y')
top_k_df = df[df[date_col].eq(date_str)].sort_values(
by=observe_col, ascending=False).head(top_k)
with plt.xkcd():
ax.clear()
# plot horizon bar
ax.barh(
top_k_df[cat_col],
top_k_df[observe_col],
color=[
color_dict.get(
x,
"#f8edeb") for x in top_k_df[cat_col]],
log=False,
left=1)
ax.invert_yaxis() # to make the biggest in the top
#dx = np.log(top_k_df[observe_col].max()) / 200
for i, (value, name) in enumerate(
zip(top_k_df[observe_col], top_k_df[cat_col])):
ax.text(
value - 20,
i,
name,
size=10,
weight=600,
ha='right',
va='center')
ax.text(
value + 0.1,
i,
f'{value:,.0f}',
size=10,
ha='left',
va='center')
ax.text(
1,
0.1,
date_str,
transform=ax.transAxes,
color='#f8edeb',
size=40,
ha='right',
weight=800)
ax.text(
0.5,
1.1,
'Covid-19',
transform=ax.transAxes,
size=14,
color='#f8edeb')
ax.text(
0.2,
0.05,
timeline_event.get(date_str, ''),
transform=ax.transAxes,
size=20,
color='#06d6a0')
ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
ax.xaxis.set_ticks_position('top')
ax.tick_params(axis='x', colors='#777777', labelsize=12)
ax.set_yticks([])
ax.margins(0, 0.01)
ax.grid(which='major', axis='x', linestyle='-')
ax.set_axisbelow(True)
plt.box(False)
複製代碼
從新調用這個新的func來製做動畫。
fargs = (df_country,
start_date,
'ObservationDate',
'Country/Region',
'Confirmed',
10,
color_dict,
ax)
animator = animation.FuncAnimation(
fig,
xkcd_bar_chart_frame,
frames=dates_delta,
fargs=fargs,
interval=1000,
repeat=False)
複製代碼
最後咱們來看一下咱們更新後的動畫效果。ps. 眼看着中國從top10中消失,眼看着America First。
保存爲MP4格式須要電腦安裝ffmep 編碼/解碼器,安裝好的ffmpeg_path須要添加到matplotlibrc 參數下。
# add ffmpeg path to matplotlibrc
plt.rcParams['animation.ffmpeg_path'] = r'your_path\ffmpeg-20200323-ba698a2-win64-static\ffmpeg-20200323-ba698a2-win64-static\bin\ffmpeg.exe'
複製代碼
本文中咱們繼續使用covid19的數據來進行可視化分析。咱們採用python 製做了酷炫的動態排名。 定義的函數能夠套用在其餘數據集中用於製做動態排名。 經過本文咱們能夠學會:
據說Youtuber 使用Bar race 製做視頻,月入50萬。