利用?Python?讓圖表動(dòng)起來
用Matplotlib
和Seaborn
這類Python
庫可以畫出很好看的圖,但是這些圖只是靜態(tài)的,難以動(dòng)態(tài)且美觀地呈現(xiàn)數(shù)值變化。要是在你下次的演示、視頻、社交媒體Po文里能用短視頻呈現(xiàn)數(shù)據(jù)變化,是不是很贊呢?更棒的是,你還是可以在你的圖表上用Matplotlib
、Seaborn
或者其他庫!
本文將使用美國國家藥物濫用研究所和疾病預(yù)防控制中心公布的藥物數(shù)據(jù),可在此處下載:https://http://www.drugabuse.gov/sites/default/files/overdosedata1999-2015.xls
我們會用到的數(shù)據(jù)是這樣的:
我們將用Matplotlib
和Seaborn
繪圖,用Numpy
和Pandas
處理數(shù)據(jù)。Matplotlib
也提供了一些我們做動(dòng)畫可以的函數(shù),所以讓我們首先導(dǎo)入所有依賴項(xiàng)。
import numpy as np import pandas as pd import seaborn as sns import matplotlib import matplotlib.pyplot as plt import matplotlib.animation as animation
然后用Pandas
載入數(shù)據(jù)并轉(zhuǎn)成DataFrame
類型的數(shù)據(jù)結(jié)構(gòu)。因?yàn)槲覀円槍Σ煌愃幬锏臑E用畫圖,寫個(gè)函數(shù)來載入感興趣的特定行的數(shù)據(jù)能避免重復(fù)代碼。(小編注:原文提供的代碼在讀取excel
文件的時(shí)候使用了已廢棄的sheetname
參數(shù),本文中已修正為sheet_name)
overdoses = pd.read_excel('overdose_data_1999-2015.xls',sheet_name='Online',skiprows =6) def get_data(table,rownum,title): data = pd.DataFrame(table.loc[rownum][2:]).astype(float) data.columns = {title} return data
現(xiàn)在讓我們來做動(dòng)畫吧!
首先,如果你和我一樣使用的是jupyter notebook
,請?jiān)诖a首行加入 %matplotlib notebook
,如此便可在notebook
直接看到生成的動(dòng)畫而非保存后才可見。
我現(xiàn)在使用 get_data
函數(shù)從表中檢索過量的數(shù)據(jù)并放在有兩列的Pandas DataFrame
中,一列是年,一列是過量死亡的人數(shù)。
%matplotlib notebook title = 'Heroin Overdoses' d = get_data(overdoses,18,title) x = np.array(d.index) y = np.array(d['Heroin Overdoses']) overdose = pd.DataFrame(y,x) #XN,YN = augment(x,y,10) #augmented = pd.DataFrame(YN,XN) overdose.columns = {title}
接下來我們初始化一個(gè)ffmpeg Writer
并以20幀每秒、1800比特率進(jìn)行錄屏。你也可以根據(jù)喜好自行設(shè)置這些值。
Writer = animation.writers['ffmpeg'] writer = Writer(fps=20, metadata=dict(artist='Me'), bitrate=1800)
(小編注:如果出現(xiàn) RuntimeError:RequestedMovieWriter(ffmpeg)notavailable
的報(bào)錯(cuò),請自行安裝ffmpeg
,裝了brew
的Mac
可以直接: brew install ffmpeg
)
現(xiàn)在我們創(chuàng)建一個(gè)有幾個(gè)標(biāo)簽的圖形。確保設(shè)置x和y軸的限制,以免動(dòng)畫隨當(dāng)前顯示的數(shù)據(jù)范圍亂跳轉(zhuǎn)。
fig = plt.figure(figsize=(10,6)) plt.xlim(1999, 2016) plt.ylim(np.min(overdose)[0], np.max(overdose)[0]) plt.xlabel('Year',fontsize=20) plt.ylabel(title,fontsize=20) plt.title('Heroin Overdoses per Year',fontsize=20)
動(dòng)畫的核心是動(dòng)畫函數(shù),你可以在其中定義視頻的每一幀發(fā)生什么。這里的 i表示動(dòng)畫中幀的索引。使用這個(gè)索引可以選擇應(yīng)在此幀中可見的數(shù)據(jù)范圍。然后我使用seaborn
線圖來繪制所選的數(shù)據(jù)。最后兩行代碼只是為了讓圖表更美觀。
def animate(i): data = overdose.iloc[:int(i+1)] #選擇數(shù)據(jù)范圍 p = sns.lineplot(x=data.index, y=data[title], data=data, color="r") p.tick_params(labelsize=17) plt.setp(p.lines,linewidth=7)
我們用調(diào)用了 animate
函數(shù)并定義了幀數(shù)的 matplotlib.animation.FuncAnimation
來開始動(dòng)畫, frames
實(shí)際上定義了調(diào)用 animate
的頻率。
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=17, repeat=True)
你可以用 ani.save()
把動(dòng)畫保存為mp4
,如果你想直接看一看動(dòng)畫效果可以用plt.show()
。
ani.save('HeroinOverdosesJumpy.mp4', writer=writer)
現(xiàn)在我們的圖表動(dòng)起來啦:
動(dòng)畫能夠正常運(yùn)行但是感覺有點(diǎn)跳躍,所以我們需要在已有數(shù)據(jù)點(diǎn)之間增加更多的數(shù)據(jù)點(diǎn)來使動(dòng)畫的過渡平滑。于是我們使用另一個(gè)函數(shù) augment
。
def augment(xold,yold,numsteps): xnew = [] ynew = [] for i in range(len(xold)-1): difX = xold[i+1]-xold[i] stepsX = difX/numsteps difY = yold[i+1]-yold[i] stepsY = difY/numsteps for s in range(numsteps): xnew = np.append(xnew,xold[i]+s*stepsX) ynew = np.append(ynew,yold[i]+s*stepsY) return xnew,ynew
現(xiàn)在我們只需要對我們的數(shù)據(jù)應(yīng)用這個(gè)函數(shù)、增加 matplotlib.animation.FuncAnimation
函數(shù)的幀數(shù)。在這里我用參數(shù) numsteps=10
調(diào)用 augment
函數(shù),也就是增加數(shù)據(jù)點(diǎn)至160個(gè),并且設(shè)置 frames=160
。這樣以來,圖表顯得更為平滑,但還是在數(shù)值變動(dòng)處有些突兀。
為了讓我們的動(dòng)畫更平滑美觀,我們可以增加一個(gè)平滑函數(shù)(具體請見:https://www.swharden.com/wp/2008-11-17-linear-data-smoothing-in-python/ )。
def smoothListGaussian(listin,strippedXs=False,degree=5): window=degree*2-1 weight=np.array([1.0]*window) weightGauss=[] for i in range(window): i=i-degree+1 frac=i/float(window) gauss=1/(np.exp((4*(frac))**2)) weightGauss.append(gauss) weight=np.array(weightGauss)*weight smoothed=[0.0]*(len(listin)-window) for i in range(len(smoothed)): smoothed[i]=sum(np.array(listin[i:i+window])*weight)/sum(weight) return smoothed
另外我們也可以加上一點(diǎn)顏色和樣式參數(shù),讓圖表更個(gè)性化。
sns.set(rc={'axes.facecolor':'lightgrey', 'figure.facecolor':'lightgrey','figure.edgecolor':'black','axes.grid':False})
當(dāng)當(dāng)當(dāng)!如此我們便得到了文章開頭的動(dòng)畫圖表。
這篇文章僅僅只是matplotlib
動(dòng)畫功能的一個(gè)例子,你大可以用它來實(shí)現(xiàn)任何一種圖表的動(dòng)畫效果。簡單調(diào)整 animate()
函數(shù)內(nèi)的參數(shù)和圖表類型,就能得到無窮無盡的可能性。
到此這篇關(guān)于利用 Python 讓圖表動(dòng)起來的文章就介紹到這了,更多相關(guān)Python 讓圖表動(dòng)起來內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python利用shutil模塊實(shí)現(xiàn)文件的裁剪與壓縮
shutil可以簡單地理解為sh+util ,shell工具的意思。shutil模塊是對os模塊的補(bǔ)充,主要針對文件的拷貝、刪除、移動(dòng)、壓縮和解壓操作。本文將利用這一模塊實(shí)現(xiàn)文件的裁剪、壓縮與解壓縮,需要的可以參考一下2022-05-05TensorFlow卷積神經(jīng)網(wǎng)絡(luò)MNIST數(shù)據(jù)集實(shí)現(xiàn)示例
這篇文章主要介紹了TensorFlow卷積神經(jīng)網(wǎng)絡(luò)MNIST數(shù)據(jù)集的實(shí)現(xiàn)示例的過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-11-11PyQt5+serial模塊實(shí)現(xiàn)一個(gè)串口小工具
這篇文章主要為大家詳細(xì)介紹了如何利用PyQt5和serial模塊實(shí)現(xiàn)一個(gè)簡單的串口小工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-01-01