Python數(shù)據(jù)可視化:箱線圖多種庫(kù)畫(huà)法
概念
箱線圖通過(guò)數(shù)據(jù)的四分位數(shù)來(lái)展示數(shù)據(jù)的分布情況。例如:數(shù)據(jù)的中心位置,數(shù)據(jù)間的離散程度,是否有異常值等。
把數(shù)據(jù)從小到大進(jìn)行排列并等分成四份,第一分位數(shù)(Q1),第二分位數(shù)(Q2)和第三分位數(shù)(Q3)分別為數(shù)據(jù)的第25%,50%和75%的數(shù)字。
四分位間距(Interquartilerange(IQR))=上分位數(shù)(upper quartile)-下分位數(shù)(lower quartile)
箱線圖分為兩部分,分別是箱(box)和須(whisker)。箱(box)用來(lái)表示從第一分位到第三分位的數(shù)據(jù),須(whisker)用來(lái)表示數(shù)據(jù)的范圍。
箱線圖從上到下各橫線分別表示:數(shù)據(jù)上限(通常是Q3+1.5IQR),第三分位數(shù)(Q3),第二分位數(shù)(中位數(shù)),第一分位數(shù)(Q1),數(shù)據(jù)下限(通常是Q1-1.5IQR)。有時(shí)還有一些圓點(diǎn),位于數(shù)據(jù)上下限之外,表示異常值(outliers)。
(注:如果數(shù)據(jù)上下限特別大,那么whisker將顯示數(shù)據(jù)的最大值和最小值。)
案例
1. 使用pandas自帶的函數(shù)
使用pandas里的dataframe數(shù)據(jù)結(jié)構(gòu)存放待顯示的數(shù)據(jù)。如果希望顯示的各個(gè)數(shù)據(jù)列表中,數(shù)據(jù)長(zhǎng)度不一致,可以先用Series函數(shù)轉(zhuǎn)換為Series數(shù)據(jù),再存儲(chǔ)到dataframe中,對(duì)應(yīng)index的value值若不存在則為NaN。
下面我們隨機(jī)生成4組數(shù)據(jù),看看他們的箱線圖。
【代碼】
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
def list_generator(mean, dis, number): # 封裝一下這個(gè)函數(shù),用來(lái)后面生成數(shù)據(jù)
return np.random.normal(mean, dis * dis, number) # normal分布,輸入的參數(shù)是均值、標(biāo)準(zhǔn)差以及生成的數(shù)量
# 我們生成四組數(shù)據(jù)用來(lái)做實(shí)驗(yàn),數(shù)據(jù)量分別為70-100
y1 = list_generator(0.8531, 0.0956, 70)
y2 = list_generator(0.8631, 0.0656, 80)
y3 = list_generator(0.8731, 0.1056, 90)
y4 = list_generator(0.8831, 0.0756, 100)
# 如果數(shù)據(jù)大小不一,記得需要下面語(yǔ)句,把數(shù)組變?yōu)閟eries
y1 = pd.Series(np.array(y1))
y2 = pd.Series(np.array(y2))
y3 = pd.Series(np.array(y3))
y4 = pd.Series(np.array(y4))
data = pd.DataFrame({"1": y1, "2": y2, "3": y3, "4": y4, })
data.boxplot() # 這里,pandas自己有處理的過(guò)程,很方便哦。
plt.ylabel("ylabel")
plt.xlabel("xlabel") # 我們?cè)O(shè)置橫縱坐標(biāo)的標(biāo)題。
plt.show()
【效果】
上面的箱線圖很簡(jiǎn)單,給出數(shù)據(jù)后,幾行代碼就能生成,不過(guò)這是簡(jiǎn)單的箱線圖。下面再看看稍微復(fù)雜點(diǎn)的。
2. 使用matplotlib庫(kù)畫(huà)箱線圖
我們上面介紹了使用pandas畫(huà)箱線圖,幾句命令就可以了。但是稍微復(fù)雜點(diǎn)的可以使用matplotlib庫(kù)。matplotlib代碼稍微復(fù)雜點(diǎn),但是很靈活。細(xì)心點(diǎn)同學(xué)會(huì)發(fā)現(xiàn)pandas里面的畫(huà)圖也是基于此庫(kù)的,下面給你看看pandas里面的源碼:
通過(guò)源碼可以看到pandas內(nèi)部也是通過(guò)調(diào)用matplotlib來(lái)畫(huà)圖的。那下面我們自己實(shí)現(xiàn)用matplotlib畫(huà)箱線圖。
我們簡(jiǎn)單模擬一下,男女生從20歲,30歲的花費(fèi)對(duì)比圖,使用箱線圖來(lái)可視化一下。
【代碼】
import numpy as np import matplotlib.pyplot as plt fig, ax = plt.subplots() # 子圖 def list_generator(mean, dis, number): # 封裝一下這個(gè)函數(shù),用來(lái)后面生成數(shù)據(jù) return np.random.normal(mean, dis * dis, number) # normal分布,輸入的參數(shù)是均值、標(biāo)準(zhǔn)差以及生成的數(shù)量 # 我們生成四組數(shù)據(jù)用來(lái)做實(shí)驗(yàn),數(shù)據(jù)量分別為70-100 # 分別代表男生、女生在20歲和30歲的花費(fèi)分布 girl20 = list_generator(1000, 29.2, 70) boy20 = list_generator(800, 11.5, 80) girl30 = list_generator(3000, 25.1056, 90) boy30 = list_generator(1000, 19.0756, 100) data=[girl20,boy20,girl30,boy30,] ax.boxplot(data) ax.set_xticklabels(["girl20", "boy20", "girl30", "boy30",]) # 設(shè)置x軸刻度標(biāo)簽 plt.show()
【效果】
從上面隨機(jī)模擬,看出來(lái)男生花費(fèi)趕不上女生吧,尤其是30歲以后,女生摔男生一大截啊。(模擬數(shù)據(jù),請(qǐng)勿當(dāng)真)
仔細(xì)看上面的圖,感覺(jué)還是不太好,既然男女生對(duì)比,那是不是要分組,男女生放一塊,然后再根據(jù)年齡段比較,這樣比較才直觀。
那我們就稍微改動(dòng)上面一點(diǎn)點(diǎn)代碼,實(shí)現(xiàn)男女生箱線圖挨得近一點(diǎn)。
【代碼】
import numpy as np import matplotlib.pyplot as plt fig, ax = plt.subplots() # 子圖 def list_generator(mean, dis, number): # 封裝一下這個(gè)函數(shù),用來(lái)后面生成數(shù)據(jù) return np.random.normal(mean, dis * dis, number) # normal分布,輸入的參數(shù)是均值、標(biāo)準(zhǔn)差以及生成的數(shù)量 # 我們生成四組數(shù)據(jù)用來(lái)做實(shí)驗(yàn),數(shù)據(jù)量分別為70-100 # 分別代表男生、女生在20歲和30歲的花費(fèi)分布 girl20 = list_generator(1000, 29.2, 70) boy20 = list_generator(800, 11.5, 80) girl30 = list_generator(3000, 25.1056, 90) boy30 = list_generator(1000, 19.0756, 100) data=[girl20,boy20,girl30,boy30,] # 用positions參數(shù)設(shè)置各箱線圖的位置 ax.boxplot(data,positions=[0, 0.6, 3, 3.7,])# 就是后面加了位置 ax.set_xticklabels(["girl20", "boy20", "girl30", "boy30",]) # 設(shè)置x軸刻度標(biāo)簽 plt.show()
【效果】
這樣看一下,是不是男女生根據(jù)年齡段分組了呢,稍微比上面好看些,也直觀一些。這樣既能看出年齡段的對(duì)比,又能看出男女生的對(duì)比。
同樣,如果想要箱線圖旋轉(zhuǎn)90°,那么也是在在 boxplot命令里加上參數(shù) vert=False即可。如果想要更多設(shè)置,可以基于 boxplot函數(shù)參數(shù)進(jìn)行修改,其函數(shù)定義如下:
boxplot(self, x, notch=None, sym=None, vert=None, whis=None, positions=None, widths=None, patch_artist=None, bootstrap=None, usermedians=None, conf_intervals=None, meanline=None, showmeans=None, showcaps=None, showbox=None, showfliers=None, boxprops=None, labels=None, flierprops=None, medianprops=None, meanprops=None, capprops=None, whiskerprops=None, manage_xticks=True, autorange=False, zorder=None)
3. 使用seaborn庫(kù)和matplotlib來(lái)畫(huà)箱線圖
Seaborn是基于matplotlib的Python可視化庫(kù)。 它提供了一個(gè)高級(jí)界面來(lái)繪制有吸引力的統(tǒng)計(jì)圖形。Seaborn其實(shí)是在matplotlib的基礎(chǔ)上進(jìn)行了更高級(jí)的API封裝,從而使得作圖更加容易,不需要經(jīng)過(guò)大量的調(diào)整就能使你的圖變得精致。但應(yīng)強(qiáng)調(diào)的是,應(yīng)該把Seaborn視為matplotlib的補(bǔ)充,而不是替代物。
函數(shù)定義:
boxplot(x=None, y=None, hue=None, data=None, order=None, hue_order=None, orient=None, color=None, palette=None, saturation=.75, width=.8, dodge=True, fliersize=5, linewidth=None, whis=1.5, notch=False, ax=None, **kwargs)
【參數(shù)講解】 x,y:dataframe中的列名(str)或者矢量數(shù)據(jù)
- data:dataframe或者數(shù)組
- palette:調(diào)色板,控制圖像的色調(diào)
- hue(str):dataframe的列名,按照列名中的值分類(lèi)形成分類(lèi)的條形圖
- order, hue_order (lists of strings):用于控制條形圖的順序
- orient:"v"|"h" 用于控制圖像使水平還是豎直顯示(這通常是從輸入變量的dtype推斷出來(lái)的,此參數(shù)一般當(dāng)不傳入x、y,只傳入data的時(shí)候使用)
- fliersize:float,用于指示離群值觀察的標(biāo)記大小
- whis:確定離群值的上下界(IQR超過(guò)低和高四分位數(shù)的比例),此范圍之外的點(diǎn)將被識(shí)別為異常值。IQR指的是上下四分位的差值。
- width:float,控制箱型圖的寬度
我們還是基于上面男女花費(fèi)案例來(lái)說(shuō),不過(guò)這里我們把數(shù)據(jù)進(jìn)行了整理,做成了數(shù)據(jù)框dataframe。
【包含的庫(kù)】
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# plt.rc("font", family="SimHei", size="15") 避免中文亂碼,可不用
【代碼第一部分】數(shù)據(jù)生成
def list_generator(mean, dis, number): # 封裝一下這個(gè)函數(shù),用來(lái)后面生成數(shù)據(jù)
return np.random.normal(mean, dis * dis, number) # normal分布,輸入的參數(shù)是均值、標(biāo)準(zhǔn)差以及生成的數(shù)量
# 我們生成四組數(shù)據(jù)用來(lái)做實(shí)驗(yàn),數(shù)據(jù)量分別為70-100
# 分別代表男生、女生在20歲和30歲的花費(fèi)分布
# 構(gòu)造數(shù)據(jù)庫(kù)DataFrame
num = 100 # 每組100個(gè)樣本
girl20 = list_generator(1000, 29.2, num)
boy20 = list_generator(800, 11.5, num)
girl30 = list_generator(3000, 25.1056, num)
boy30 = list_generator(1000, 19.0756, num)
girl_sex = ['female' for _ in range(num)]
boy_sex = ['male' for _ in range(num)]
age20 = [20 for _ in range(num)]
age30 = [30 for _ in range(num)]
girl_d1 = pd.DataFrame({'cost': girl20, 'sex': girl_sex, 'age': age20})
boy_d1 = pd.DataFrame({'cost': boy20, 'sex': boy_sex, 'age': age20})
girl_d2 = pd.DataFrame({'cost': girl30, 'sex': girl_sex, 'age': age30})
boy_d2 = pd.DataFrame({'cost': boy30, 'sex': boy_sex, 'age': age30})
data = pd.concat([girl_d1, boy_d1, girl_d2, boy_d2])
print(data.head())
數(shù)據(jù)長(zhǎng)啥樣?下面是給出的數(shù)據(jù)框前面的部分,一共400個(gè)樣本,分性別和年齡。
【代碼第二部分】使用seaborn庫(kù)畫(huà)圖
簡(jiǎn)單看看所有數(shù)據(jù)的分布情況:
sns.boxplot(x="age", y="cost", data=data, hue="sex", width=0.5, linewidth=1.0, palette="Set3")
根據(jù)性別分組:
sns.boxplot(x="age", y="cost", data=data, hue="sex", width=0.5, linewidth=1.0, palette="Set3")
根據(jù)年齡分組:
sns.boxplot(x="sex", y="cost", data=data, hue="age", width=0.5, linewidth=1.0, palette="Set3")
上面這些是seaborn庫(kù)的簡(jiǎn)單使用,可以通過(guò)年齡看男女花費(fèi)比較,也可以根據(jù)性別看不同年齡段的花費(fèi)比較,還是比較直觀的。當(dāng)然除此之外還有很多其他的炫技,大家可以自己嘗試。
總結(jié)
從上面來(lái)看,雖然我們是采用不同方法來(lái)畫(huà)箱線圖,但是最基本的都是調(diào)用matplotlib庫(kù),這里面pandas是最簡(jiǎn)單的箱線圖可視化,但是不靈活。而matplotlib雖然靈活,但是需要慢慢調(diào),而且復(fù)雜。相比之下seaborn更加酷炫,而且圖還更好看。上面例子都是本人親測(cè),一個(gè)個(gè)對(duì)比,原創(chuàng)文章,大家如果有其他問(wèn)題可以留言討論。
相關(guān)文章
使用pyinstaller打包PySide2程序中遇到的問(wèn)題
說(shuō)到打包,我們就需要用到python程序的打包工具pyinstaller了,這個(gè)包安裝簡(jiǎn)單,使用同樣簡(jiǎn)單,下面這篇文章主要給大家介紹了關(guān)于使用pyinstaller打包PySide2程序中遇到的問(wèn)題,需要的朋友可以參考下2023-05-05
Python實(shí)現(xiàn)獲取某天是某個(gè)月中的第幾周
這篇文章主要介紹了Python實(shí)現(xiàn)獲取某天是某個(gè)月中的第幾周,本文代碼實(shí)現(xiàn)獲取指定的某天是某個(gè)月中的第幾周、周一作為一周的開(kāi)始,需要的朋友可以參考下2015-02-02
解決mnist數(shù)據(jù)集下載的相關(guān)問(wèn)題
這篇文章主要介紹了解決mnist數(shù)據(jù)集下載的相關(guān)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
Python+Matplotlib實(shí)現(xiàn)繪制三維折線圖
立體圖視覺(jué)上層次分明色彩鮮艷,具有很強(qiáng)的視覺(jué)沖擊力,讓觀看的人駐景時(shí)間長(zhǎng),留下深刻的印象。今天我們就通過(guò)這篇文章來(lái)了解如何用python中的matplotlib庫(kù)繪制漂亮的三維折線圖吧2023-03-03
簡(jiǎn)單講解Python中的數(shù)字類(lèi)型及基本的數(shù)學(xué)計(jì)算
這篇文章主要介紹了Python中的數(shù)字類(lèi)型及基本的數(shù)學(xué)計(jì)算,與其他語(yǔ)言一樣,除法相對(duì)復(fù)雜些,不過(guò)本文并未就此深入,需要的朋友可以參考下2016-03-03
Tensorflow 模型轉(zhuǎn)換 .pb convert to .lite實(shí)例
今天小編就為大家分享一篇Tensorflow 模型轉(zhuǎn)換 .pb convert to .lite實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-02-02
python調(diào)用自定義函數(shù)的實(shí)例操作
在本文里我們給大家整理了關(guān)于python調(diào)用自定義函數(shù)的實(shí)例操作相關(guān)內(nèi)容,有此需要的朋友們可以學(xué)習(xí)參考下。2019-06-06
Python 實(shí)現(xiàn)「食行生鮮」簽到領(lǐng)積分功能
今天我們就用 Python 來(lái)實(shí)現(xiàn)自動(dòng)簽到,省得我每天打開(kāi) APP 來(lái)操作了。感興趣的朋友跟隨小編一起看看吧2018-09-09

