數(shù)據(jù)分析-可視化工具matplotlib
一、數(shù)據(jù)分析的流程
①提出問題:明確想干什么;
②準(zhǔn)備數(shù)據(jù):將數(shù)據(jù)取出,進(jìn)行預(yù)處理,以獲得我們需要的數(shù)據(jù);
③分析數(shù)據(jù):使用工具、模型對(duì)數(shù)據(jù)進(jìn)行分析;
④獲得結(jié)論;
⑤結(jié)論可視化:將結(jié)論以圖的形式展現(xiàn),使分析結(jié)果清晰明了、易懂;
二、對(duì)比常用統(tǒng)計(jì)圖
(1)折線圖
以折線(線條)的上升下降來表示統(tǒng)計(jì)數(shù)量的增減變化的統(tǒng)計(jì)圖,特點(diǎn)是:能夠顯示數(shù)據(jù)的變化趨勢(shì),反映事物隨某個(gè)變量(如時(shí)間)的變化情況。簡單的折線圖如下:(源自matplotlib官網(wǎng))

(2)直方圖
直方圖又稱質(zhì)量分布圖,是表示資料變化情況的重要工具。直方圖由一系列高度不同的縱向條紋或者線段表示數(shù)據(jù)的分布情況,一般用橫軸表示數(shù)據(jù)范圍,用縱軸表示分布情況。例如用直方圖表示某學(xué)校各個(gè)年齡段各有多少人。繪制直方圖需要確定組數(shù)和組距,即將數(shù)據(jù)分為多少組,相鄰兩組之間的間隔是多少,比如繪制(年齡-人數(shù))的直方圖時(shí),設(shè)置組距為5,即每一組的范圍分別為(05歲)、(610歲)....組數(shù)=(max(x)-min(x))/組距。組距的選擇十分重要,通常情況下,應(yīng)該盡量選擇合適的組距使組數(shù)為整數(shù)。
直方圖也分為頻數(shù)直方圖和頻率直方圖,即縱軸分別表示該組的數(shù)量和頻率。
特點(diǎn):繪制連續(xù)性的數(shù)據(jù),展示一組或者多組數(shù)據(jù)的分布情況。直方圖示例如下:(來自matplotlib官網(wǎng))

(3)條形圖
條形圖是用來顯示各個(gè)不同的事物對(duì)于某一個(gè)共同屬性的比較情況,例如已知2019年各個(gè)城市的GDP,那么用條形圖可以很直觀的展示各個(gè)城市的GDP情況以及他們的對(duì)比關(guān)系。
特點(diǎn):繪制離散的數(shù)據(jù),能夠一眼看出各個(gè)數(shù)據(jù)的大小,比較數(shù)據(jù)之間的差別。條形圖示例如下:(來自matplotlib官網(wǎng))

(4)散點(diǎn)圖
散點(diǎn)圖表示在回歸分析中,數(shù)據(jù)點(diǎn)在直角坐標(biāo)系的分布情況。繪制散點(diǎn)圖時(shí),用兩組數(shù)據(jù)構(gòu)成多個(gè)坐標(biāo)點(diǎn),考察坐標(biāo)點(diǎn)的分布,判斷兩個(gè)變量之間是否存在某種關(guān)聯(lián)或者總結(jié)坐標(biāo)點(diǎn)的分布模式、分布情況。
特點(diǎn):判斷變量之間是否存在數(shù)量關(guān)聯(lián)趨勢(shì),展示離群點(diǎn)(分布規(guī)律)散點(diǎn)圖示例如下:(來自matplotlib官網(wǎng))

三、matplotlib繪制常用統(tǒng)計(jì)圖
(1)繪制折線圖
案例一:
假設(shè)一天中每個(gè)兩個(gè)小時(shí)的氣溫分別是:15,13,14.5,17,20,25,26,26,26,27,22,18,15;使matplotlib畫出該圖形。代碼如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
# 數(shù)據(jù)在x軸的位置,是一個(gè)可迭代對(duì)象
x =range(2, 26, 2)
y = [15, 13, 14.5, 17, 20, 25, 26, 26, 24, 22, 18, 15]
plt.plot(x, y)
plt.show()
運(yùn)行之后結(jié)果如下圖:

在上圖中,我們通過對(duì)函數(shù)plt.plot()傳入兩個(gè)列表參數(shù)x, y,便可以繪制折線圖,然后調(diào)用函數(shù)plt.show()將繪制結(jié)果顯示出來。但是通過觀察上圖,發(fā)現(xiàn)還存在一下問題:
①圖片大小不夠
②圖片沒有描述信息
③x,y軸的刻度顯示不明確(刻度間距不合適)
④線條樣式可能不合適
針對(duì)上述問題,修改代碼如下所示:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
# 設(shè)置圖片大小,以及dpi
plt.figure(figsize=(10, 8), dpi=80)
# 設(shè)置字體顯示為指定的文件(windows路徑為:)適用于各種操作系統(tǒng)
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
# 數(shù)據(jù)在x軸的位置,是一個(gè)可迭代對(duì)象
x =range(2, 26, 2)
y = [15, 13, 14.5, 17, 20, 25, 26, 26, 24, 22, 18, 15]
plt.plot(x, y)
# 設(shè)置x軸的刻度 可以傳一個(gè)range(),也可以傳一個(gè)列表, 列表元素為坐標(biāo)軸各點(diǎn)的值
plt.xticks(x)
# plt.xticks(range(2, 25))
# 設(shè)置y軸的刻度
plt.yticks(range(min(y), max(y)+1))
# 設(shè)置x,y軸的標(biāo)簽以及圖片標(biāo)題
plt.xlabel("時(shí)間", fontproperties=my_font)
plt.ylabel("溫度(℃)", fontproperties=my_font)
plt.title("一天中氣溫變化情況(每隔兩小時(shí))", fontproperties=my_font)
# 保存圖片在繪制之后
# 可以保存為.svg這種矢量圖格式,放大之后不會(huì)有鋸齒
plt.savefig("./p1.png")
plt.show()
運(yùn)行結(jié)果如下:

案例二:
如果列表a表示十點(diǎn)到十一點(diǎn)兩個(gè)小時(shí)之間每一分鐘氣溫的變化,繪圖表示。
代碼如下:
from matplotlib import pyplot as plt
from matplotlib import font_manager
import random
# 設(shè)置圖片大小,以及dpi
plt.figure(figsize=(10, 8), dpi=80)
# 設(shè)置字體顯示為指定的文件(windows路徑為:)適用于各種操作系統(tǒng)my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
x = range(0, 120)
y = [random.randint(25, 30)for i in range(120)]
plt.plot(x, y)
# 調(diào)整x軸的刻度_x = list(x) # 只有列表才能取步長,所以進(jìn)行強(qiáng)制轉(zhuǎn)換_xtick_labels = ["10點(diǎn){}分".format(i)for i in range(60)]
_xtick_labels += ["11點(diǎn){}分".format(i)for i in range(60)]
plt.xticks(_x[::5], _xtick_labels[::5], rotation=45, fontproperties=my_font) # 取步長為5,旋轉(zhuǎn)270度,rotation表示旋轉(zhuǎn)的度數(shù)# 添加描述信息plt.xlabel("時(shí)間", fontproperties=my_font)
plt.ylabel("溫度 單位(℃)", fontproperties=my_font)
plt.title("10點(diǎn)到12點(diǎn)每分鐘的氣溫變化情況", fontproperties=my_font)
plt.show()
結(jié)果如下圖:

案例三:
假設(shè)大家在30歲的時(shí)候,根據(jù)自己的實(shí)際情況統(tǒng)計(jì)出來了11歲到30歲每年交的男女朋友的數(shù)量如列表[1,0,1,1,3,4,3,2,3,4,4,5,6,5,4,3,3,1,1,1] ,以及某位朋友的上述情況列表[0,2,3,5,2,1, 1,0,3,4,6,3,1,1,0,2,1,1,3,2]。請(qǐng)繪制出該數(shù)據(jù)的折線圖,以便分析每年交男女朋友的數(shù)量走勢(shì)。
代碼如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
# 設(shè)置字體
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
# 設(shè)置圖的大小
plt.figure(figsize=(14, 7), dpi=80)
x =range(11, 31)
y = [1, 0, 1, 1, 3, 4, 3, 2, 3, 4, 4, 5, 6, 5, 4, 3, 3, 1, 1, 1]
y1 = [0, 2, 3, 5, 2, 1, 1, 0, 3, 4, 6, 3, 1, 1, 0, 2, 1, 1, 3, 2]
plt.plot(x, y, label="自己", color="orange", linestyle=":")
plt.plot(x, y1, label="同桌", color="cyan", linestyle="--")
# 設(shè)置x軸顯示信息
x_labels = ["{}歲".format(i)for i in range(11, 31)]
_x =list(x)
plt.xticks(_x, x_labels, fontproperties=my_font)
plt.yticks(range(min(y), max(y)+2))
# 繪制網(wǎng)格
plt.grid(alpha=0.5)# alpha 表示透明度
# 添加描述信息
plt.xlabel("年齡(歲)", fontproperties=my_font)
plt.ylabel("男(女)朋友數(shù)量(個(gè))", fontproperties=my_font)
plt.title("11歲到30歲每年所處對(duì)象的數(shù)量走勢(shì)圖", fontproperties=my_font)
# 添加圖例
# 調(diào)用此方法之后,程序會(huì)結(jié)合plt.plot()方法中的label參數(shù)顯示出圖例
# 此方法接收字體的參數(shù)為prop
plt.legend(prop=my_font)
plt.show()
結(jié)果如下:

plt.plot()方法的參數(shù):
@ label: 用來在plt.legend()方法調(diào)用時(shí)設(shè)置圖例
@ color: 設(shè)置線條顏色
@ linestyle: 設(shè)置線條風(fēng)格
@ linewidth: 設(shè)置線條粗細(xì)
matplotlib折線圖總結(jié):
·繪制折線圖(plt.plot()方法)
·設(shè)置圖片大小和分辨率(plt.figure()方法)
·實(shí)現(xiàn)圖片保存(plt.savefig()方法)
·設(shè)置xy軸的刻度和字符串(plt.xticks())
·解決刻度稀疏或者密集的問題(plt.xticks()方法)
·設(shè)置標(biāo)題、xy軸的label(title,xlabel,ylabel)
·設(shè)置字體(font_manager類,結(jié)合fontproperties參數(shù))
·添加圖例(plt.plot(label=”xx”),plt.legend()方法)
(2)繪制散點(diǎn)圖
案例:
假設(shè)你通過爬蟲獲取到了北京2016年3,10月份每天白天的最高氣溫(分別位于列表a,b)那么此時(shí)如何尋找出氣溫隨時(shí)間變化的某種規(guī)律?
代碼如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
# 設(shè)置圖片大小,設(shè)置分辨率
plt.figure(figsize=(14, 9), dpi=80)
y_3 = [11, 17, 16, 11, 12, 11, 6, 6, 7, 8, 9, 12, 15, 14, 17, 18
,21, 16, 17, 20, 14, 15, 15, 15, 19, 21, 22, 22, 22, 23, 21]
y_10 = [26, 26, 28, 19, 21, 17, 16, 19, 18, 20, 20, 19, 22, 23, 17,
20, 21, 20, 22, 15, 11, 15, 5, 13, 17, 10, 11, 13, 12, 13, 6]
x_3 =range(1, 32)
x_10 =range(40, 71)
# 繪制
plt.scatter(x_3, y_3, label="三月")
plt.scatter(x_10, y_10, label="十月")
# 調(diào)整x軸刻度
_x =list(x_3) +list(x_10)
_xticks_labels = ["3月{}日".format(i)for i in x_3]
_xticks_labels += ["10月{}日".format(i)for i in x_10]
plt.xticks(_x[::3], _xticks_labels[::3], fontproperties=my_font, rotation=45, fontsize=12)
# 設(shè)置附加信息
plt.xlabel("時(shí)間", fontproperties=my_font, fontsize=14)
plt.ylabel("溫度(℃)", fontproperties=my_font, fontsize=14)
plt.title("三月與十月的最高氣溫趨勢(shì)圖", fontproperties=my_font, fontsize=14)
# 添加圖例
plt.legend(prop=my_font)
plt.show()
結(jié)果如下:

(3)繪制條形圖
案例一:
假設(shè)你獲取到了2017年內(nèi)地電影票房前20的電影列表a和電影票房數(shù)據(jù)列表b,那么如何更加直觀的展示該數(shù)據(jù)?
代碼如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
a = ["戰(zhàn)狼2", "速度與激情8", "功夫瑜伽", "西游伏妖篇", "變形金剛", "最后的騎士",
"摔跤吧爸爸", "加勒比海盜5:死無對(duì)證", "金剛:骷髏島", "極限特工:終極回歸",
"生化危機(jī)6:終章", "乘風(fēng)破浪", "神偷奶爸3", "智取威虎山", "大鬧天竺", "金剛狼3:殊死一戰(zhàn)",
"蜘蛛俠:英雄歸來", "悟空傳", "銀河護(hù)衛(wèi)隊(duì)", "情圣"]
b = [56.01, 26.94, 17.53, 16.49, 15.45, 12.96, 11.8, 11.61, 11.28, 11.12,
10.49, 10.3, 8.75, 7.55, 7.32, 6.99, 6.88, 6.86, 6.58, 6.32]
plt.figure(figsize=(15, 10), dpi=80)
# 豎著的條形圖# plt.bar(range(len(a)), b)
# plt.xticks(range(len(a)), a, fontproperties=my_font, rotation=90)
# 橫著的條形圖# 某些情況下橫著的條形圖比豎著的好看plt.barh(range(len(a)), b, height=0.3)
# 設(shè)置附加信息plt.xlabel("票房 單位(億)", fontproperties=my_font)
# y軸刻度信息plt.yticks(range(len(a)), a, fontproperties=my_font)
plt.grid(alpha=0.3)
plt.show()
結(jié)果如下:

案例二:
假設(shè)你知道了列表a中電影分別在2017-09-14(b_14),2017-09-15(b_15),2017-09-16三天的票房,為了展示列表中電影本身的票房以及同其他電影數(shù)據(jù)的對(duì)比情況,應(yīng)該如何更加直觀的呈現(xiàn)該數(shù)據(jù)?
代碼如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
plt.figure(figsize=(14, 9), dpi=80)
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
a = ["星球崛起3", "敦刻爾克", "蜘蛛俠", "戰(zhàn)狼2"]
b_16 = [15746, 312, 4497, 319]
b_15 = [12357, 156, 2045, 168]
b_14 = [2358, 399, 2358, 362]
x_14 =list(range(len(a)))
x_15 = [i +0.3 for i in x_14]
x_16 = [i +0.3*2 for i in x_14]
print(len(x_14))
plt.bar(x_14, b_14, width=0.3, label="2017-09-14")
plt.bar(x_15, b_15, width=0.3, label="2017-09-15")
plt.bar(x_16, b_16, width=0.3, label="2017-09-16")
# 設(shè)置x軸的刻度
plt.xticks(list(x_15), a, fontproperties=my_font, fontsize=12)
# 設(shè)置圖例
plt.legend()
plt.show()
注意:為了使條形圖不重疊,應(yīng)當(dāng)使每個(gè)條形的位置向右偏移一定距離,并且滿足:
條形寬度*條形數(shù)量<1,比如上述代碼中的x_14,x_15,x_16的設(shè)置。
結(jié)果如下:

(4)繪制直方圖
直方圖的應(yīng)用場(chǎng)景:
·用戶的年齡狀態(tài)
·一段時(shí)間內(nèi)用戶點(diǎn)擊次數(shù)的分布狀態(tài)
·用戶活躍時(shí)間的分布狀態(tài)
案例一:
頻數(shù)分布直方圖,假設(shè)你獲取了250部電影的時(shí)長列表a,希望統(tǒng)計(jì)出這些電影時(shí)長的分布狀態(tài)(比如時(shí)長為100分鐘到120分鐘的電影的數(shù)量,出現(xiàn)的頻率)等信息,你應(yīng)該如何呈現(xiàn)這些數(shù)據(jù)?(ps: 由于數(shù)據(jù)量比較大,因此使用隨機(jī)數(shù)模擬上述數(shù)據(jù))
代碼如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
import random
# 設(shè)置組距為5,設(shè)置組距的時(shí)候應(yīng)該注意盡量使(max(a)-min(a))能夠整除組距
dis =5
a = [random.randint(80, 150)for i in range(251)]
# 組數(shù)
num_bin = (max(a)-min(a))//dis
plt.hist(a, num_bin)# 參數(shù)normed=1表示畫出的圖形是頻率分布直方圖
# 設(shè)置x軸的刻度
plt.xticks(range(min(a), max(a)+dis, dis))
plt.grid()
plt.show()
注:在組數(shù)為正整數(shù)的情況下,圖形能正確繪制,當(dāng)實(shí)際組數(shù)為小數(shù)時(shí)(即(max(a)-min(a))/dis為小數(shù)),獲得的圖形會(huì)有一定的偏移(如圖十四,組數(shù)實(shí)際為小數(shù))。解決方法為調(diào)整組距,使組數(shù)為正整數(shù)。
結(jié)果為:


案例二:
在美國 2004的人口普查發(fā)現(xiàn)有124million的人在離家較遠(yuǎn)的地方工作。根據(jù)他們從家里到上班地點(diǎn)所需要的時(shí)間,通過抽樣統(tǒng)計(jì)列出了下表的數(shù)據(jù),這些數(shù)據(jù)能夠繪制成直方圖嗎?
interval = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 60, 90] (表示各個(gè)區(qū)間)
width = [5, 5, 5, 5, 5, 5, 5, 5, 5, 15, 30, 60] (表示區(qū)間寬度)
quantity = [836, 2737, 3723, 3926, 3596, 1438, 3273, 642, 824, 613, 215, 47] (各區(qū)間頻數(shù))
分析:由于數(shù)據(jù)以及被統(tǒng)計(jì)好了,因此不能直接使用直方圖畫圖函數(shù)plt.hist(),該函數(shù)會(huì)在使用時(shí)分析一遍各個(gè)區(qū)間的頻數(shù)。(但是理論上如果用隨機(jī)數(shù)來模擬原始數(shù)據(jù),應(yīng)該可以用直方圖畫圖函數(shù)來繪制出圖形)。由于數(shù)據(jù)已經(jīng)統(tǒng)計(jì)好,因此直接使用條形圖,使條形圖的線條寬度占滿x軸的一個(gè)區(qū)間,即圖形直觀上是直方圖。
代碼如下:
from matplotlibimport pyplotas plt
from matplotlibimport font_manager
import random
my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simsun.ttc")
# 只需要設(shè)置條形圖的寬度為1即可
plt.figure(figsize=(12, 8), dpi=80)
interval = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 60, 90]
width = [5, 5, 5, 5, 5, 5, 5, 5, 5, 15, 30, 60]
quantity = [836, 2737, 3723, 3926, 3596, 1438, 3273, 642, 824, 613, 215, 47]
plt.bar(range(12), quantity, width=1)
_x = [i -0.5 for iin range(13)]
_xlabels = interval + [150]
plt.xticks(_x, _xlabels)
plt.ylabel("人數(shù)", fontproperties=my_font, fontsize=12)
plt.xlabel("時(shí)間", fontproperties=my_font, fontsize=12)
plt.grid()
plt.show()

四、總結(jié)
matplotlib使用流程:
·明確問題
·選擇圖形的呈現(xiàn)形式
·準(zhǔn)備數(shù)據(jù)
·繪圖和圖形完善
matplotlib更多圖形樣式:
百度echart(前端應(yīng)用,使用js)。
plotly:可視化工具,兼容matplotlib和pandas。(需要付費(fèi))
<本文檔記錄個(gè)人學(xué)習(xí)matplotlib繪圖工具過程的總結(jié)!若有不當(dāng)之處歡迎指正! >