動態(tài)排名柱狀圖的兩種做法

受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é)果如下:


示例gif

數(shù)據(jù)整理

先將故障硬件的名稱捧颅、故障數(shù)量和發(fā)生日期整理好。好在這些數(shù)據(jù)一直以來都有不定期梳理较雕。梳理后的格式如下:


整理后的數(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太大辜腺,只截部分):


生成gif

方法二:現(xiàn)成的“輪子”

從ID來看休建,應(yīng)該就是B站視頻的原作者在GitHub上的一個庫(見“參考2”)乍恐,使用的是d3.js的前端作圖。只要將數(shù)據(jù)整理成規(guī)定的格式测砂,直接從網(wǎng)頁導(dǎo)入即可茵烈。也可以修改一些簡單的配置,非常好用砌些,在此推薦一下呜投。
最后一幀截圖:


最后一幀

參考

  1. Embedding Matplotlib Animations in Jupyter as Interactive JavaScript Widgets
  2. 手把手教你制作一個動態(tài)炫酷的可視化圖表(歷年中國大學(xué)學(xué)術(shù)排行榜)
  3. 用Matplotlib的animation.FuncAnimation畫動畫
  4. matplotlib圖例中文亂碼?
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市存璃,隨后出現(xiàn)的幾起案子仑荐,更是在濱河造成了極大的恐慌,老刑警劉巖纵东,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粘招,死亡現(xiàn)場離奇詭異,居然都是意外死亡偎球,警方通過查閱死者的電腦和手機洒扎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甜橱,“玉大人逊笆,你說我怎么就攤上這事∑癜粒” “怎么了难裆?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長镊掖。 經(jīng)常有香客問我乃戈,道長,這世上最難降的妖魔是什么亩进? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任症虑,我火速辦了婚禮,結(jié)果婚禮上归薛,老公的妹妹穿的比我還像新娘谍憔。我一直安慰自己,他們只是感情好主籍,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布习贫。 她就那樣靜靜地躺著,像睡著了一般千元。 火紅的嫁衣襯著肌膚如雪苫昌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天幸海,我揣著相機與錄音祟身,去河邊找鬼奥务。 笑死,一個胖子當(dāng)著我的面吹牛袜硫,可吹牛的內(nèi)容都是我干的氯葬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼父款,長吁一口氣:“原來是場噩夢啊……” “哼溢谤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起憨攒,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤世杀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肝集,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞻坝,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年杏瞻,在試婚紗的時候發(fā)現(xiàn)自己被綠了所刀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡捞挥,死狀恐怖浮创,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情砌函,我是刑警寧澤斩披,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站讹俊,受9級特大地震影響垦沉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仍劈,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一厕倍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贩疙,春花似錦讹弯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至芍躏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間降狠,已是汗流浹背对竣。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工庇楞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人否纬。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓吕晌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親临燃。 傳聞我的和親對象是個殘疾皇子睛驳,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 這個點早睡的人已經(jīng)進入夢鄉(xiāng)了乏沸,晚睡的夜貓子還在加班熬夜。每當(dāng)夜晚入眠時爪瓜,腦海里總會無意間掠過這一天的鏡頭蹬跃,...
    天涯浪石閱讀 394評論 0 3
  • 作為一個媽媽,我要檢討铆铆,媽媽雖然心里愛你蝶缀,嘴上也愛你,但媽媽確實沒有做到時時刻刻關(guān)注你薄货,給你愛的關(guān)懷翁都,那可能是因為...
    啦啦啦_97ca閱讀 480評論 0 1
  • 日式土豆可樂餅,解決了典型北方人老媽即將發(fā)芽的土豆谅猾,姥爺很愛吃吶柄慰, 下雪啦,很大的雪~ 我們的雪人? 花千骨看完了...
    宅蕊茜茜閱讀 166評論 0 0
  • 有三個迷途的青年敦野赊瞬、翔太先煎、幸平在逃跑途中路過一家廢棄的雜貨鋪,剛好開的車又壞了巧涧,不得已躲進那家雜貨鋪避一晚上薯蝎。就...
    木子張閱讀 488評論 0 4