受B站拜年祭發(fā)射最多的彈幕是什么?視頻啟發(fā)溉苛,對日常維護工作中的故障硬件也做了一次盤點。這里介紹兩種方法弄诲,第一種是Python + Matplotlib愚战;第二種是利用GitHub上現(xiàn)成的“輪子”。如果需要快速出圖齐遵,后者更簡單(也更美觀)寂玲。
方法一:Python
MATPLOTLIB的動畫類
MATPLOTLIB包含了一個動畫類——Animation,用這個類就可以實現(xiàn)圖標(biāo)的動畫效果梗摇。先看下官方文檔給出的例子:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()xdata, ydata = [], []ln, = plt.plot([], [], 'ro')
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
xdata.append(frame)
ydata.append(np.sin(frame))
ln.set_data(xdata, ydata)
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=True)plt.show()
上例中拓哟,init初始化圖表,update函數(shù)則負責(zé)更新圖表中的數(shù)據(jù)留美。最主要的是FuncAnimation彰檬,通過不斷調(diào)用update伸刃,并將frames參數(shù)中的值依次傳遞給update,更新圖表逢倍。這個例子的運行結(jié)果如下:
數(shù)據(jù)整理
先將故障硬件的名稱捧颅、故障數(shù)量和發(fā)生日期整理好。好在這些數(shù)據(jù)一直以來都有不定期梳理较雕。梳理后的格式如下:
保存成csv后由pandas讀取到DataFrame中碉哑,同時解析日期:
with open('plugin_faults.csv', 'r') as f:
data = pd.read_csv(f, parse_dates=['date'])
因為柱狀圖中每根柱的長度是個累計值,而表中的是當(dāng)天故障的數(shù)量亮蒋,因此要按故障硬件名稱累積求和:
data = data.sort_values('date')
group = data.groupby('name')
data['value_cumsum'] = group.cumsum()
data.sort_values(['date','value_cumsum','name'], inplace=True)
data.drop_duplicates(['date','name'], keep='last', inplace=True)
填充所有日期扣典,所有硬件類型
plugins = ['PCU', '電源板', 'AS7-D', 'ESB24-D', 'CPU', 'HWAT-B', 'SW256B', 'SWPRO-C',
'ETP', 'ET16', '時鐘板', 'DRAM', 'TR3T', '硬盤', 'HDSAM-A', 'DCAR1-A', '光模塊', '熔絲', '網(wǎng)管交換機'] # 所有硬件名稱
start = datetime(2017,1,1) # 開始日期
end = datetime(2019,12,31) # 結(jié)束日期
dates = [start + timedelta(days=i) for i in range((end - start).days + 1)]
index = pd.MultiIndex.from_product([dates, plugins], names = ["date", "name"]) # 3年內(nèi)所有日期與硬件名稱的笛卡爾積作為多重索引
df = pd.DataFrame(index=index)
df['value'] = data.set_index(['date', 'name'])['value_cumsum'] # 向DataFrame填入data中的數(shù)據(jù)
df = df.unstack(level=1).fillna(method='ffill') # 將硬件名稱索引unstack,前向填充累計故障數(shù)(比如累計到昨天一共壞n件慎玖,而今天沒有該硬件故障贮尖,則累計數(shù)量還是n件)
df = df.stack(dropna=False).reset_index().fillna(0) # 轉(zhuǎn)換成無索引的DataFrame,并填充缺失值為0(從開始時間直至第一個同類型硬件發(fā)生故障的值均為缺失值)
至此數(shù)據(jù)整理部分結(jié)束趁怔,得到了2017至2019年共計3年內(nèi)每天每種硬件故障的累計數(shù)的DataFrame湿硝。
作圖
通過水平柱狀圖將故障硬件的數(shù)量進行排名可視化,每個柱一個顏色润努,由多到少自上往下排列关斜。
水平柱狀圖用barh生成,動畫需更新每日的排序铺浇,但同一種硬件的顏色不能改變痢畜,因此初始化了plugin_color字典。
update函數(shù)中的df_i為當(dāng)前幀所使用的數(shù)據(jù)鳍侣,以日期作為篩選標(biāo)準(zhǔn)丁稀。
fig, ax = plt.subplots()
# 分配顏色的字典
colormap = [i / len(plugins) * 0.7 + 0.15 for i, _ in enumerate(plugins)]
colormap = plt.get_cmap('Paired')(colormap)
plugin_color = {plugins[i]: colormap[i] for i in range(len(plugins))}
def update(i):
date = datetime(2017, 1, 1) + timedelta(days=i)
# 篩選當(dāng)日的數(shù)據(jù),按數(shù)量排序
df_i = df[df['date'] == date]
df_i = df_i.sort_values('value', ascending=True)
names = df_i['name'] # 硬件名稱作為Y軸標(biāo)簽
colors = [plugin_color[name] for name in names]
value = df_i['value'] # X軸的值
ax.clear() # 清理ax倚聚,否則排序不會重做
x = max(value) * 0.85 # 圖中日期標(biāo)簽的水平相對位置
if i == 0:
ax.set_xlim(0, 1.05)
x = 0.85
# 水平柱狀圖
rects = ax.barh(y=names,
width=value,
align='center',
height=0.5,
color=colors)
# 每個柱的數(shù)字標(biāo)簽
for i, v in enumerate(value):
ax.text(v + 0.1, i, int(v), color=colors[i], ha='left', va='center')
# 日期標(biāo)簽
ax.text(x, 0.5, date.strftime('%Y-%m-%d'),
fontweight='bold', fontsize='25', color='red')
return rects
生成動畫對象二驰,回調(diào)函數(shù)為update,frames傳入3年的日期數(shù)秉沼,interval定義每一幀的時延(每秒8幀)。
blit我試了下沒感覺有啥區(qū)別矿酵,按照官方文檔的說法唬复,是一種比較老的繪圖技術(shù),這里設(shè)成False全肮。
repeat控制是否循環(huán)播放敞咧。
ani = animation.FuncAnimation(fig=fig,
func=update,
frames=int(len(df) / len(plugins)),
interval=1000/8, # 每幀之間的時延,單位:ms
blit=False,
repeat=False)
保存為視頻或GIF:
ani.save('test.gif', dpi=10, writer='pillow')
ani.save('test.mp4')
如果要在jupyter notebook中直接顯示(中文顯示問題參見“參考3”):
%matplotlib inline
from IPython.display import HTML
HTML(ani.to_html5_video())
生成的動態(tài)排名柱狀圖GIF(完整的GIF太大辜腺,只截部分):
方法二:現(xiàn)成的“輪子”
從ID來看休建,應(yīng)該就是B站視頻的原作者在GitHub上的一個庫(見“參考2”)乍恐,使用的是d3.js的前端作圖。只要將數(shù)據(jù)整理成規(guī)定的格式测砂,直接從網(wǎng)頁導(dǎo)入即可茵烈。也可以修改一些簡單的配置,非常好用砌些,在此推薦一下呜投。
最后一幀截圖: