前言
文不如字,字不如表,表不如圖”,說的就是可視化的重要性。從事與數據相關的工作者經常會作一些總結或展望性的報告,如果報告中密密麻麻都是文字,相信聽眾或者老板一定會厭煩;如果報告中呈現的是大量的圖形化結果,就會受到眾人的喜愛,因為圖形更加直觀、醒目。
本章內容的重點就是利用Python繪制常見的統計圖形,例如條形圖、餅圖、直方圖、折線圖、散點圖等,通過這些常用圖形的展現,將復雜的數據簡單化。這些圖形的繪制可以通過matplotlib模塊、pandas模塊或者seaborn模塊實現。通過本章內容的學習,讀者將會掌握以下幾個方面的知識點:
- 離散型數據都有哪些可用的可視化方法;
- 數值型的單變量可用哪些圖形展現;
- 多維數值之間的關系表達;
- 如何將多個圖形繪制到一個畫框內。
6.1 離散型變量的可視化
如果你需要使用數據可視化的方法來表達離散型變量的分布特征,例如統計某APP用戶的性別比例、某產品在各區域的銷售量分布、各年齡段內男女消費者的消費能力差異等。對于類似這些離散型變量的統計描述,可以使用餅圖或者條形圖對其進行展現。接下來,通過具體的案例來學習餅圖和條形圖的繪制,進而掌握Python的繪圖技能。
6.1.1 餅圖
餅圖屬于最傳統的統計圖形之一(1801年由William Playfair首次發布使用),它幾乎隨處可見,例如大型公司的屏幕墻、各種年度論壇的演示稿以及各大媒體發布的數據統計報告等。
首先,需要讀者了解有關餅圖的原理。餅圖是將一個圓分割成不同大小的楔形,而圓中的每一個楔形代表了不同的類別值,通常會根據楔形的面積大小來判斷類別值的差異。如圖6-1所示,就是一個由不同大小的楔形組成的餅圖。
對于這樣的餅圖,該如何通過Python完成圖形的繪制呢?其實很簡單,通過matplotlib模塊和pandas模塊都可以非常方便地得到一個漂亮的餅圖。下面舉例說明如何利用Python實現餅圖的繪制。
1.matplotlib模塊
如果你選擇matplotlib模塊繪制餅圖的話,首先需要導入該模塊的子模塊pyplot,然后調用模塊中的pie函數。關于該函數的語法和參數含義如下:
pie(x, explode=None, labels=None, colors=None, autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1, startangle=None, radius=None, counterclock=True, wedgeprops=None, textprops=None, center=(0, 0), frame=False)
- x:指定繪圖的數據。
- explode:指定餅圖某些部分的突出顯示,即呈現爆炸式。
- labels:為餅圖添加標簽說明,類似于圖例說明。
- colors:指定餅圖的填充色。
- autopct:自動添加百分比顯示,可以采用格式化的方法顯示。
- pctdistance:設置百分比標簽與圓心的距離。
- shadow:是否添加餅圖的陰影效果。
- labeldistance:設置各扇形標簽(圖例)與圓心的距離。
- startangle:設置餅圖的初始擺放角度。 radius:設置餅圖的半徑大小。
- counterclock:是否讓餅圖按逆時針順序呈現。
- wedgeprops:設置餅圖內外邊界的屬性,如邊界線的粗細、顏色等。
- textprops:設置餅圖中文本的屬性,如字體大小、顏色等。
- center:指定餅圖的中心點位置,默認為原點。
- frame:是否要顯示餅圖背后的圖框,如果設置為True的話,需要同時控制圖框x軸、y軸的范圍和餅圖的中心位置。
該函數的參數雖然比較多,但是應用起來非常靈活,而且繪制的餅圖也比較好看。下面以“芝麻信用”失信用戶數據為例(數據來源于財新網),分析近300萬失信人群的學歷分布,pie函數繪制餅圖的詳細代碼如下:
# 餅圖的繪制
# 導入第三方模塊
import matplotlib.pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號
# 構造數據
edu = [0.2515,0.3724,0.3336,0.0368,0.0057]
labels = ['中專','大專','本科','碩士','其他']
# 繪制餅圖
plt.pie(x = edu, # 繪圖數據
labels=labels, # 添加教育水平標簽
autopct='%.1f%%' # 設置百分比的格式,這里保留一位小數
)
# 添加圖標題
plt.title('失信用戶的教育水平分布')
# 顯示圖形
plt.show()
結果:
圖6-2所示就是一個不加任何修飾的餅圖。這里只給pie函數傳遞了三個核心參數,即繪圖的數據、每個數據代表的含義(學歷標簽)以及給餅圖添加數值標簽。很顯然,這樣的餅圖并不是很完美,例如餅圖看上去并不成正圓、餅圖沒有對應的標題、沒有突出顯示餅圖中的某個部分等。下面進一步對該餅圖做一些修飾,盡可能讓餅圖看起來更加舒服,代碼如下:
# 添加修飾的餅圖
explode = [0,0.1,0,0,0] # 生成數據,用于突出顯示大專學歷人群
colors=['#9999ff','#ff9999','#7777aa','#2442aa','#dd5555'] # 自定義顏色
# 中文亂碼和坐標軸負號的處理
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 將橫、縱坐標軸標準化處理,確保餅圖是一個正圓,否則為橢圓
plt.axes(aspect='equal')
# 繪制餅圖
plt.pie(x = edu, # 繪圖數據
explode=explode, # 突出顯示大專人群
labels=labels, # 添加教育水平標簽
colors=colors, # 設置餅圖的自定義填充色
autopct='%.1f%%', # 設置百分比的格式,這里保留一位小數
pctdistance=0.8, # 設置百分比標簽與圓心的距離
labeldistance = 1.1, # 設置教育水平標簽與圓心的距離
startangle = 180, # 設置餅圖的初始角度
radius = 1.2, # 設置餅圖的半徑
counterclock = False, # 是否逆時針,這里設置為順時針方向
wedgeprops = {'linewidth': 1.5, 'edgecolor':'green'},# 設置餅圖內外邊界的屬性值
textprops = {'fontsize':10, 'color':'black'}, # 設置文本標簽的屬性值
)
# 添加圖標題
plt.title('失信用戶的受教育水平分布')
# 顯示圖形
plt.show()
結果:
如上呈現的餅圖,直觀上要比之前的餅圖好看很多,這些都是基于pie函數的靈活參數所實現的。餅圖中突出顯示大專學歷的人群,是因為在這300萬失信人群中,大專學歷的人數比例最高,該功能就是通過explode參數完成的。另外,還需要對如上餅圖的繪制說明幾點:
- 如果繪制的圖形中涉及中文及數字中的負號,都需要通過rcParams進行控制。
- 由于不加修飾的餅圖更像是一個橢圓,所以需要pyplot模塊中的axes函數將橢圓強制為正圓。
- 自定義顏色的設置,既可以使用十六進制的顏色,也可以使用具體的顏色名稱,如red、black等。
- 如果需要添加圖形的標題,需要調用pyplot模塊中的title函數。
- 代碼plt.show()用來呈現最終的圖形,無論是使用Jupyter或Pycharm編輯器,都需要使用這行代碼呈現圖形。
2.pandas模塊
細心的讀者一定會發現,在前面的幾個章節中或多或少地應用到pandas模塊的繪圖“方法”plot,該方法可以針對序列和數據框繪制常見的統計圖形,例如折線圖、條形圖、直方圖、箱線圖、核密度圖等。同樣,plot也可以繪制餅圖,接下來簡單介紹一下該方法針對序列的應用和參數含義:
Series.plot(kind='line', ax=None, figsize=None, use_index=True, title=None, grid=None, legend=False, style=None, logx=False, logy=False, loglog=False, xticks=None, yticks=None, xlim=None, ylim=None, rot=None, fontsize=None, colormap=None, table=False, yerr=None, xerr=None, label=None, secondary_y=False, **kwds)
- kind:指定一個字符串值,用于繪制圖形的類型,默認為折線圖line。還可以繪制垂直條形圖bar、水平條形圖hbar、直方圖hist、箱線圖box、核密度圖kde、面積圖area和餅圖pie。
- ax:控制當前子圖在組圖中的位置。例如,在一個2×2的圖形矩陣中,通過該參數控制當前圖形在矩陣中的位置。
- figsize:控制圖形的寬度和高度,以元組形式傳遞,即(width,hright)。
- use_index:bool類型的參數,是否將序列的行索引用作x軸的刻度,默認為True。
- title:用以添加圖形的標題。
- grid:bool類型的參數,是否給圖形添加網格線,默認為False。
- legend:bool類型的參數,是否添加子圖的圖例,默認為False。
- style:如果kind為line,該參數可以控制折線圖的線條類型。
- logx:bool類型的參數,是否對x軸做對數變換,默認為False。
- logy:bool類型的參數,是否對y軸做對數變換,默認為False。
- loglog:bool類型的參數,是否同時對x軸和y軸做對數變換,默認為False。
- xticks:用于設置x軸的刻度值。 yticks:用于設置y軸的刻度值。
- xlim:以元組或列表的形式,設置x軸的取值范圍,如(0,3)表示x軸落在0~3的范圍之內。
- ylim:以元組或列表的形式,設置y軸的取值范圍。 rot:接受一個整數值,用于旋轉刻度值的角度。
- fontsize:接受一個整數,用于控制x軸與y軸刻度值的字體大小。
- colormap:接受一個表示顏色含義的字符串,或者Python的色彩映射對象,該參數用于設置圖形的區域顏色。
- table:該參數如果為True,表示在繪制圖形的基礎上再添加數據表;如果傳遞的是序列或數據框,則根據數據添加數據表。
- yerr:如果kind為bar或hbar,該參數表示在條形圖的基礎上添加誤差棒。
- xerr:含義同yerr參數。
- label:用于添加圖形的標簽。
- secondary_y:bool類型的參數,是否添加第二個y軸,默認為False。
- **kwds:關鍵字參數,該參數可以根據不同的kind值,為圖形添加更多的修飾性參數(依賴于pyplot中的繪圖函數)。
pandas模塊中的plot“方法”可以根據kind參數繪制不同的統計圖形,而且也包含了其他各種靈活的參數。除此,根據不同的kind參數值,可以調用更多對應的關鍵字參數**kwds,這些關鍵字參數都源于pyplot中的繪圖函數。
為了幫助讀者更好地理解plot方法繪制的統計圖形,這里仍然以失信用戶數據為例,繪制學歷的分布餅圖,詳細代碼如下:
# 導入第三方模塊
import pandas as pd
# 構建序列
data1 = pd.Series({'中專':0.2515,'大專':0.3724,'本科':0.3336,'碩士':0.0368,'其他':0.0057})
# 將序列的名稱設置為空字符,否則繪制的餅圖左邊會出現None這樣的字眼
data1.name = ''
# 控制餅圖為正圓
plt.axes(aspect = 'equal')
# plot方法對序列進行繪圖
data1.plot(kind = 'pie', # 選擇圖形類型
autopct='%.1f%%', # 餅圖中添加數值標簽
radius = 1, # 設置餅圖的半徑
startangle = 180, # 設置餅圖的初始角度
counterclock = False, # 將餅圖的順序設置為順時針方向
title = '失信用戶的受教育水平分布', # 為餅圖添加標題
wedgeprops = {'linewidth': 1.5, 'edgecolor':'green'}, # 設置餅圖內外邊界的屬性值
textprops = {'fontsize':10, 'color':'black'} # 設置文本標簽的屬性值
)
# 顯示圖形
plt.show()
結果:
如圖6-4所示,應用pandas模塊中的plot方法,也可以得到一個比較好看的餅圖。該方法中除了kind參數和title參數屬于plot方法,其他參數都是pyplot模塊中pie函數的參數,并且以關鍵字參數的形式調用。
6.1.2 條形圖
雖然餅圖可以很好地表達離散型變量在各水平上的差異(如會員的性別比例、學歷差異、等級高低等),但是其不擅長對比差異不大或水平值過多的離散型變量,因為餅圖是通過各楔形面積的大小來表示數值的高低,而人類對扇形面積的比較并不是特別敏感。如果讀者手中的數據恰好不適合用餅圖展現,可以選擇另一種常用的可視化方法,即條形圖。
以垂直條形圖為例,離散型變量在各水平上的差異就是比較柱形的高低,柱體越高,代表的數值越大,反之亦然。在Python中,可以借助matplotlib、pandas和seaborn模塊完成條形圖的繪制。下面將采用這三個模塊繪制條形圖。
1.matplotlib模塊
應用matplotlib模塊繪制條形圖,需要調用bar函數,關于該函數的語法和參數含義如下:
bar(x, height, width=0.8, bottom=None, color=None, edgecolor=None, linewidth=None, tick_label=None, xerr=None, yerr=None, label = None, ecolor=None, align, log=False, **kwargs)
- x:傳遞數值序列,指定條形圖中x軸上的刻度值。
- height:傳遞數值序列,指定條形圖y軸上的高度。
- width:指定條形圖的寬度,默認為0.8。
- bottom:用于繪制堆疊條形圖。
- color:指定條形圖的填充色。
- edgecolor:指定條形圖的邊框色。
- linewidth:指定條形圖邊框的寬度,如果指定為0,表示不繪制邊框。
- tick_label:指定條形圖的刻度標簽。
- xerr:如果參數不為None,表示在條形圖的基礎上添加誤差棒。
- yerr:參數含義同xerr。
- label:指定條形圖的標簽,一般用以添加圖例。
- ecolor:指定條形圖誤差棒的顏色。
- align:指定x軸刻度標簽的對齊方式,默認為center,表示刻度標簽居中對齊,如果設置為edge,則表示在每個條形的左下角呈現刻度標簽。
- log:bool類型參數,是否對坐標軸進行log變換,默認為False。
- **kwargs:關鍵字參數,用于對條形圖進行其他設置,如透明度等。
bar函數的參數同樣很多,希望讀者能夠認真地掌握每個參數的含義,以便使用時得心應手。下面將基于該函數繪制三類條形圖,分別是單變量的垂直或水平條形圖、堆疊條形圖和水平交錯條形圖。
(1)垂直或水平條形圖
首先來繪制單個離散變量的垂直或水平條形圖,數據來源于互聯網,反映的是2017年中國六大省份的GDP,繪圖代碼如下:
# 條形圖的繪制--垂直條形圖
# 讀入數據
GDP = pd.read_excel(r'D:\PyProject\data\Province GDP 2017.xlsx')
# 設置繪圖風格(不妨使用R語言中的ggplot2風格)
plt.style.use('ggplot')
# 繪制條形圖
plt.bar(x = range(GDP.shape[0]), # 指定條形圖x軸的刻度值
height = GDP.GDP, # 指定條形圖y軸的數值
tick_label = GDP.Province, # 指定條形圖x軸的刻度標簽
color = 'steelblue', # 指定條形圖的填充色
)
# 添加y軸的標簽
plt.ylabel('GDP(萬億)')
# 添加條形圖的標題
plt.title('2017年度6個省份GDP分布')
# 為每個條形圖添加數值標簽
for x,y in enumerate(GDP.GDP):
plt.text(x,y+0.1,'%s' %round(y,1),ha='center')
# 顯示圖形
plt.show()
結果:
如圖6-5所示,該條形圖比較清晰地反映了6個省份GDP的差異。針對如上代碼需要做幾點解釋:
- 條形圖中灰色網格的背景是通過代碼plt.style.use(‘ggplot’)實現的,如果不添加該行代碼,則條形圖為白底背景。
- 如果添加圖形的x軸或y軸標簽,需要調用pyplot子模塊中的xlab和ylab函數。
- 由于bar函數沒有添加數值標簽的參數,因此使用for循環對每一個柱體添加數值標簽,使用的核心函數是pyplot子模塊中的text。該函數的參數很簡單,前兩個參數用于定位字符在圖形中的位置,第三個參數表示呈現的具體字符值,第四個參數為ha,表示字符的水平對齊方式為居中對齊。
站在閱讀者的角度來看,該條形圖可能并不是很理想,因為不能快速地發現哪個省份GDP最高或最低。如果將該條形圖進行降序或升序處理,可能會更直觀一些。這里就以水平條形圖為例,代碼如下:
# 條形圖的繪制--水平條形圖
# 對讀入的數據作升序排序
GDP.sort_values(by = 'GDP', inplace = True)
# 繪制條形圖
plt.barh(y = range(GDP.shape[0]), # 指定條形圖y軸的刻度值
width = GDP.GDP, # 指定條形圖x軸的數值
tick_label = GDP.Province, # 指定條形圖y軸的刻度標簽
color = 'steelblue', # 指定條形圖的填充色
)
# 添加x軸的標簽
plt.xlabel('GDP(萬億)')
# 添加條形圖的標題
plt.title('2017年度6個省份GDP分布')
# 為每個條形圖添加數值標簽
for y,x in enumerate(GDP.GDP):
plt.text(x+0.1,y,'%s' %round(x,1),va='center')
# 顯示圖形
plt.show()
結果:
圖6-6所示就是經過排序的水平條形圖(實際上是垂直條形圖的軸轉置)。需要注意的是,水平條形圖不再是bar函數,而是barh函數。讀者可能疑惑,為什么對原始數據做升序排序,但是圖形看上去是降序(從上往下)?那是因為水平條形圖的y軸刻度值是從下往上布置的,所以條形圖從下往上是滿足升序的。
(2)堆疊條形圖
正如前文所介紹的,不管是垂直條形圖還是水平條形圖,都只是反映單個離散變量的統計圖形,如果想通過條形圖傳遞兩個離散變量的信息該如何做到?相信讀者一定見過堆疊條形圖,該類型條形圖的橫坐標代表一個維度的離散變量,堆疊起來的“塊”代表了另一個維度的離散變量。這樣的條形圖,最大的優點是可以方便比較累積和,那這種條形圖該如何通過Python繪制呢?這里以2017年四個季度的產業值為例(數據來源于中國統計局),繪制堆疊條形圖,詳細代碼如下:
# 條形圖的繪制--堆疊條形圖
# 讀入數據
Industry_GDP = pd.read_excel(r'D:\PyProject\data\Industry_GDP.xlsx')
# 取出四個不同的季度標簽,用作堆疊條形圖x軸的刻度標簽
Quarters = Industry_GDP.Quarter.unique()
# 取出第一產業的四季度值
Industry1 = Industry_GDP.GPD[Industry_GDP.Industry_Type == '第一產業']
# 重新設置行索引
Industry1.index = range(len(Quarters))
# 取出第二產業的四季度值
Industry2 = Industry_GDP.GPD[Industry_GDP.Industry_Type == '第二產業']
# 重新設置行索引
Industry2.index = range(len(Quarters))
# 取出第三產業的四季度值
Industry3 = Industry_GDP.GPD[Industry_GDP.Industry_Type == '第三產業']
# 繪制堆疊條形圖
# 各季度下第一產業的條形圖
plt.bar(x = range(len(Quarters)), height=Industry1, color = 'steelblue', label = '第一產業', tick_label = Quarters)
# 各季度下第二產業的條形圖
plt.bar(x = range(len(Quarters)), height=Industry2, bottom = Industry1, color = 'green', label = '第二產業')
# 各季度下第三產業的條形圖
plt.bar(x = range(len(Quarters)), height=Industry3, bottom = Industry1 + Industry2, color = 'red', label = '第三產業')
# 添加y軸標簽
plt.ylabel('生成總值(億)')
# 添加圖形標題
plt.title('2017年各季度三產業總值')
# 顯示各產業的圖例
plt.legend()
# 顯示圖形
plt.show()
結果:
如上就是一個典型的堆疊條形圖,雖然繪圖的代碼有些偏長,但是其思想還是比較簡單的,就是分別針對三種產業的產值繪制三次條形圖。需要注意的是,第二產業的條形圖是在第一產業的基礎上做了疊加,故需要將bottom參數設置為Industry1;而第三產業的條形圖又是疊加在第一和第二產業之上,所以需要將bottom參數設置為Industry1+ Industry2。
讀者可能疑惑,通過條件判斷將三種產業的值(Industry1、Industry2、Industry3)分別取出來后,為什么還要重新設置行索引?那是因為各季度下每一種產業值前的行索引都不相同,這就導致無法進行Industry1+ Industry2的和計算(讀者不妨試試不改變序列Industry1和Industry2的行索引的后果)。
(3)水平交錯條形圖 堆疊條形圖可以包含兩個離散變量的信息,而且可以比較各季度整體產值的高低水平,但是其缺點是不易區分“塊”之間的差異,例如二、三季度的第三產業值差異就不是很明顯,區分高低就相對困難。而交錯條形圖恰好就可以解決這個問題,該類型的條形圖就是將堆疊的“塊”水平排開,如想繪制這樣的條形圖,可以參考下方代碼(數據來源于胡潤財富榜,反映的是5個城市億萬資產超高凈值家庭數):
# 條形圖的繪制--水平交錯條形圖
# 導入第三方模塊
import numpy as np
# 讀入數據
HuRun = pd.read_excel(r'D:\PyProject\data\HuRun.xlsx')
# 取出城市名稱
Cities = HuRun.City.unique()
# 取出2016年各城市億萬資產家庭數
Counts2016 = HuRun.Counts[HuRun.Year == 2016]
# 取出2017年各城市億萬資產家庭數
Counts2017 = HuRun.Counts[HuRun.Year == 2017]
# 繪制水平交錯條形圖
bar_width = 0.4
plt.bar(x = np.arange(len(Cities)), height = Counts2016, label = '2016', color = 'steelblue', width = bar_width)
plt.bar(x = np.arange(len(Cities))+bar_width, height = Counts2017, label = '2017', color = 'indianred', width = bar_width)
# 添加刻度標簽(向右偏移0.225)
plt.xticks(np.arange(5)+0.2, Cities)
# 添加y軸標簽
plt.ylabel('億萬資產家庭數')
# 添加圖形標題
plt.title('近兩年5個城市億萬資產家庭數比較')
# 添加圖例
plt.legend()
# 顯示圖形
plt.show()
結果:
圖6-8反映的是2016年和2017年5大城市億萬資產家庭數的條形圖,可以很好地比較不同年份下的差異。例如,這5個城市中,2017年的億萬資產家庭數較2016年都有所增加。
但是對于這種數據,就不適合使用堆疊條形圖,因為堆疊條形圖可以反映總計的概念。如果將2016年和2017年億萬資產家庭數堆疊計總,就會出現問題,因為大部分家庭數在這兩年內都被重復統計在胡潤財富榜中,計算出來的總和會被擴大。
另外,再對如上的代碼做三點解釋,希望能夠幫助讀者解去疑惑:
- 如上的水平交錯條形圖,其實質就是使用兩次bar函數,所不同的是,第二次bar函數使得條形圖往右偏了0.4個單位(left=np.arange(len(Cities))+bar_width),進而形成水平交錯條形圖的效果。
- 每一個bar函數,都必須控制條形圖的寬度(width=bar_width),否則會導致條形圖的重疊。
- 如果利用bar函數的tick_label參數添加條形圖x軸上的刻度標簽,會發現標簽并不是居中對齊在兩個條形圖之間,為了克服這個問題,使用了pyplot子模塊中的xticks函數,并且使刻度標簽的位置向右移0.2個單位。
2.pandas模塊
通過pandas模塊繪制條形圖仍然使用plot方法,該“方法”的語法和參數含義在前文已經詳細介紹過,但是plot方法存在一點瑕疵,那就是無法繪制堆疊條形圖。下面通過該模塊的plot方法繪制單個離散變量的垂直條形圖或水平條形圖以及兩個離散變量的水平交錯條形圖,代碼如下:
# Pandas模塊之垂直或水平條形圖
# 繪圖(此時的數據集在前文已經按各省GDP做過升序處理)
GDP.GDP.plot(kind = 'bar', width = 0.8, rot = 0, color = 'steelblue', title = '2017年度6個省份GDP分布')
# 添加y軸標簽
plt.ylabel('GDP(萬億)')
# 添加x軸刻度標簽
plt.xticks(range(len(GDP.Province)), #指定刻度標簽的位置
GDP.Province # 指出具體的刻度標簽值
)
# 為每個條形圖添加數值標簽
for x,y in enumerate(GDP.GDP):
plt.text(x-0.1,y+0.2,'%s' %round(y,1),va='center')
# 顯示圖形
plt.show()
結果:
只要掌握matplotlib模塊繪制單個離散變量的條形圖方法,就可以套用到pandas模塊中的plot方法,兩者是相通的。讀者可以嘗試plot方法繪制水平條形圖,這里就不再給出參考代碼了。
接下來使用plot方法繪制含兩個離散變量的水平交錯條形圖,具體代碼如下:
# Pandas模塊之水平交錯條形圖
HuRun_reshape = HuRun.pivot_table(index = 'City', columns='Year', values='Counts').reset_index()
# 對數據集降序排序
HuRun_reshape.sort_values(by = 2016, ascending = False, inplace = True)
HuRun_reshape.plot(x = 'City', y = [2016,2017], kind = 'bar', color = ['steelblue', 'indianred'],
rot = 0, # 用于旋轉x軸刻度標簽的角度,0表示水平顯示刻度標簽
width = 0.8, title = '近兩年5個城市億萬資產家庭數比較')
# 添加y軸標簽
plt.ylabel('億萬資產家庭數')
plt.xlabel('')
plt.show()
如上代碼所示,應用plot方法繪制水平交錯條形圖,必須更改原始數據集的形狀,即將兩個離散型變量的水平值分別布置到行與列中(代碼中采用透視表的方法實現),最終形成的表格變換如圖6-10所示。
針對變換后的數據,可以使用plot方法實現水平交錯條形圖的繪制,從代碼量來看,要比使用matplotlib模塊簡短一些,得到的條形圖如圖6-11所示。
3.seaborn模塊繪制條形圖
seaborn模塊是一款專門用于繪制統計圖形的利器,通過該模塊寫出來的代碼也是非常通俗易懂的。該模塊并不在Anoconda集成工具中,故需要讀者另行下載。下面就簡單介紹一下如何通過該模塊完成條形圖的繪制(同樣無法繪制堆疊條形圖)。
# seaborn模塊之垂直或水平條形圖
# 導入第三方模塊
import seaborn as sns
sns.barplot(y = 'Province', # 指定條形圖x軸的數據
x = 'GDP', # 指定條形圖y軸的數據
data = GDP, # 指定需要繪圖的數據集
color = 'steelblue', # 指定條形圖的填充色
orient = 'horizontal' # 將條形圖水平顯示
)
# 重新設置x軸和y軸的標簽
plt.xlabel('GDP(萬億)')
plt.ylabel('')
# 添加圖形的標題
plt.title('2017年度6個省份GDP分布')
# 為每個條形圖添加數值標簽
for y,x in enumerate(GDP.GDP):
plt.text(x,y,'%s' %round(x,1),va='center')
# 顯示圖形
plt.show()
結果:
如上代碼就是通過seaborn模塊中的barplot函數實現單個離散變量的條形圖。除此之外,seaborn模塊中的barplot函數還可以繪制兩個離散變量的水平交錯條形圖,所以有必要介紹一下該函數的用法及重要參數含義:
sns.barplot(x=None, y=None, hue=None, data=None, order=None, hue_order=None, ci=95, n_boot=1000, orient=None, color=None, palette=None, saturation=0.75, errcolor='.26', errwidth=None, dodge=True, ax=None, **kwargs)
- x:指定條形圖的x軸數據。
- y:指定條形圖的y軸數據。 -
- hue:指定用于分組的另一個離散變量。
- data:指定用于繪圖的數據集。
- order:傳遞一個字符串列表,用于分類變量的排序。
- hur_order:傳遞一個字符串列表,用于分類變量hue值的排序。
- ci:用于繪制條形圖的誤差棒(置信區間)。
- n_boot:當指定ci參數時,可以通過n_boot參數控制自助抽樣的迭代次數。
- orient:指定水平或垂直條形圖。
- color:指定所有條形圖所屬的一種填充色。
- palette:指定hue變量中各水平的顏色。
- saturation:指定顏色的透明度。
- errcolor:指定誤差棒的顏色。
- errwidth:指定誤差棒的線寬。
- capsize:指定誤差棒兩端線條的長度。
- dodge:bool類型參數,當使用hue參數時,是否繪制水平交錯條形圖,默認為True。
- ax:用于控制子圖的位置。
- **kwagrs:關鍵字參數,可以調用plt.bar函數中的其他參數。
為了說明如上函數中的參數,這里以泰坦尼克號數據集為例,繪制水平交錯條形圖,代碼如下:
# 讀入數據
Titanic = pd.read_csv(r'D:\PyProject\data\titanic_train.csv')
# 繪制水平交錯條形圖
sns.barplot(x = 'Pclass', # 指定x軸數據
y = 'Age', # 指定y軸數據
hue = 'Sex', # 指定分組數據
data = Titanic, # 指定繪圖數據集
palette = 'RdBu', # 指定男女性別的不同顏色
errcolor = 'blue', # 指定誤差棒的顏色
errwidth=2, # 指定誤差棒的線寬
saturation = 1, # 指定顏色的透明度,這里設置為無透明度
capsize = 0.05 # 指定誤差棒兩端線條的寬度
)
# 添加圖形標題
plt.title('各船艙等級中男女乘客的年齡差異')
# 顯示圖形
plt.show()
結果:
如圖6-13所示,繪制的每一個條形圖中都含有一條豎線,該豎線就是條形圖的誤差棒,即各組別下年齡的標準差大小。從圖6-13可知,三等艙的男性乘客年齡是最為接近的,因為標準差最小。
需要注意的是,數據集Titanic并非匯總好的數據,是不可以直接應用到matplotlib模塊中的bar函數與pandas模塊中的plot方法。如需使用,必須先對數據集進行分組聚合,關于分組聚合的內容已經在第5章中介紹過,讀者可以前去了解。
6.2 數值型變量的可視化
很多時候,我們拿到手的數據都包含大量的數值型變量,在對數值型變量進行探索和分析時,一般都會應用到可視化方法。而本節的重點就是介紹如何使用Python實現數值型變量的可視化,通過本節內容的學習,讀者將會掌握如何使用matplotlib模塊、pandas模塊和seaborn模塊繪制直方圖、核密度圖、箱線圖、小提琴圖、折線圖以及面積圖。
6.2.1 直方圖與核密度曲線
直方圖一般用來觀察數據的分布形態,橫坐標代表數值的均勻分段,縱坐標代表每個段內的觀測數量(頻數)。一般直方圖都會與核密度圖搭配使用,目的是更加清晰地掌握數據的分布特征,下面將詳細介紹該類型圖形的繪制。
1.matplotlib模塊
matplotlib模塊中的hist函數就是用來繪制直方圖的。關于該函數的語法及參數含義如下:
plt.hist(x, bins=10, range=None, normed=False, weights=None, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, color=None, label=None, stacked=False)
- x:指定要繪制直方圖的數據。
- bins:指定直方圖條形的個數。
- range:指定直方圖數據的上下界,默認包含繪圖數據的最大值和最小值。
- normed:是否將直方圖的頻數轉換成頻率。
- weights:該參數可為每一個數據點設置權重。
- cumulative:是否需要計算累計頻數或頻率。
- bottom:可以為直方圖的每個條形添加基準線,默認為0。
- histtype:指定直方圖的類型,默認為bar,除此之外,還有barstacked、step和stepfilled。
- align:設置條形邊界值的對齊方式,默認為mid,另外還有left和right。
- orientation:設置直方圖的擺放方向,默認為垂直方向。
- rwidth:設置直方圖條形的寬度。
- log:是否需要對繪圖數據進行log變換。
- color:設置直方圖的填充色。
- edgecolor:設置直方圖邊框色。
- label:設置直方圖的標簽,可通過legend展示其圖例。
- stacked:當有多個數據時,是否需要將直方圖呈堆疊擺放,默認水平擺放。
這里不妨以Titanic數據集為例繪制乘客的年齡直方圖,具體代碼如下:
# matplotlib模塊繪制直方圖
# 檢查年齡是否有缺失
any(Titanic.Age.isnull())
# 不妨刪除含有缺失年齡的觀察
Titanic.dropna(subset=['Age'], inplace=True)
# 繪制直方圖
plt.hist(x = Titanic.Age, # 指定繪圖數據
bins = 20, # 指定直方圖中條塊的個數
color = 'steelblue', # 指定直方圖的填充色
edgecolor = 'black' # 指定直方圖的邊框色
)
# 添加x軸和y軸標簽
plt.xlabel('年齡')
plt.ylabel('頻數')
# 添加標題
plt.title('乘客年齡分布')
# 顯示圖形
plt.show()
結果:
如圖6-14所示,就是關于乘客年齡的直方圖分布。需要注意的是,如果原始數據集中存在缺失值,
一定要對缺失觀測進行刪除或替換
,否則無法繪制成功。如果在直方圖的基礎上再添加核密度圖,通過matplotlib模塊就比較吃力了,因為首先得計算出每一個年齡對應的核密度值。為了簡單起見,下面利用pandas模塊中的plot方法將直方圖和核密度圖繪制到一起。
2.pandas模塊
# Pandas模塊繪制直方圖和核密度圖
# 繪制直方圖
Titanic.Age.plot(kind = 'hist', bins = 20, color = 'steelblue', edgecolor = 'black', density = True, label = '直方圖')
# 繪制核密度圖
Titanic.Age.plot(kind = 'kde', color = 'red', label = '核密度圖')
# 添加x軸和y軸標簽
plt.xlabel('年齡')
plt.ylabel('核密度值')
# 添加標題
plt.title('乘客年齡分布')
# 顯示圖例
plt.legend()
# 顯示圖形
plt.show()
結果:
如圖6-15所示,Python的核心代碼就兩行,分別是利用plot方法繪制直方圖和核密度圖。需要注意的是,在直方圖的基礎上添加核密度圖,必須將直方圖的頻數更改為頻率,即normed(新版本為density)參數設置為True。
3.seaborn模塊
盡管這幅圖滿足了兩種圖形的合成,但其表達的是所有乘客的年齡分布,如果按性別分組,研究不同性別下年齡分布的差異,該如何實現?針對這個問題,使用matplotlib模塊或pandas模塊都會稍微復雜一些,推薦使用seaborn模塊中的distplot函數,因為該函數的代碼簡潔而易懂。關于該函數的語法和參數含義如下:
sns.distplot(a, bins=None, hist=True, kde=True, rug=False, fit=None, hist_kws=None, kde_kws=None, rug_kws=None, fit_kws=None, color=None, vertical=False, norm_hist=False, axlabel=None, label=None, ax=None)
- a:指定繪圖數據,可以是序列、一維數組或列表。
- bins:指定直方圖條形的個數。
- hist:bool類型的參數,是否繪制直方圖,默認為True。
- kde:bool類型的參數,是否繪制核密度圖,默認為True。
- rug:bool類型的參數,是否繪制須圖(如果數據比較密集,該參數比較有用),默認為False。
- fit:指定一個隨機分布對象(需調用scipy模塊中的隨機分布函數),用于繪制隨機分布的概率密度曲線。
- hist_kws:以字典形式傳遞直方圖的其他修飾屬性,如填充色、邊框色、寬度等。
- kde_kws:以字典形式傳遞核密度圖的其他修飾屬性,如線的顏色、線的類型等。
- rug_kws:以字典形式傳遞須圖的其他修飾屬性,如線的顏色、線的寬度等。
- fit_kws:以字典形式傳遞概率密度曲線的其他修飾屬性,如線條顏色、形狀、寬度等。
- color:指定圖形的顏色,除了隨機分布曲線的顏色。
- vertical:bool類型的參數,是否將圖形垂直顯示,默認為True。
- norm_hist:bool類型的參數,是否將頻數更改為頻率,默認為False。
- axlabel:用于顯示軸標簽。 label:指定圖形的圖例,需結合plt.legend()一起使用。
- ax:指定子圖的位置。
從函數的參數可知,通過該函數,可以實現三種圖形的合成,分別是直方圖(hist參數)、核密度曲線(kde參數)以及指定的理論分布密度曲線(fit參數)。接下來,針對如上介紹的distplot函數,繪制不同性別下乘客的年齡分布圖,具體代碼如下:
# seaborn模塊繪制分組的直方圖和核密度圖
# 取出男性年齡
Age_Male = Titanic.Age[Titanic.Sex == 'male']
# 取出女性年齡
Age_Female = Titanic.Age[Titanic.Sex == 'female']
# 繪制男女乘客年齡的直方圖
sns.distplot(Age_Male, bins = 20, kde = False, hist_kws = {'color':'steelblue'}, label = '男性')
# 繪制女性年齡的直方圖
sns.distplot(Age_Female, bins = 20, kde = False, hist_kws = {'color':'purple'}, label = '女性')
plt.title('男女乘客的年齡直方圖')
# 顯示圖例
plt.legend()
# 顯示圖形
plt.show()
# 繪制男女乘客年齡的核密度圖
sns.distplot(Age_Male, hist = False, kde_kws = {'color':'red', 'linestyle':'-'},
norm_hist = True, label = '男性')
# 繪制女性年齡的核密度圖
sns.distplot(Age_Female, hist = False, kde_kws = {'color':'black', 'linestyle':'--'},
norm_hist = True, label = '女性')
plt.title('男女乘客的年齡核密度圖')
# 顯示圖例
plt.legend()
# 顯示圖形
plt.show()
結果:
如圖6-16所示,為了避免四個圖形混在一起不易發現數據背后的特征,將直方圖與核密度圖分開繪制。從直方圖來看,女性年齡的分布明顯比男性矮,說明在各年齡段下,男性乘客要比女性乘客多;再看核密度圖,男女性別的年齡分布趨勢比較接近,說明各年齡段下的男女乘客人數同步增加或減少。
6.2.2 箱線圖
箱線圖是另一種體現數據分布的圖形,通過該圖可以得知數據的下須值(Q1-1.5IQR)、下四分位數(Q1)、中位數(Q2)、均值、上四分位(Q3)數和上須值(Q3+1.5IQR),更重要的是,箱線圖還可以發現數據中的異常點。
箱線圖的繪制仍然可以通過matplotlib模塊、pandas模塊和seaborn模塊完成,下面將一一介紹各模塊繪制條形圖的過程。
1.matplotlib模塊
首先介紹一下matplotlib模塊中繪制箱線圖的boxplot函數,有關該函數的語法和參數含義如下:
plt.boxplot(x, notch=None, sym=None, vert=None, whis=None, positions=None, widths=None, patch_artist=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)
- x:指定要繪制箱線圖的數據。
- notch:是否以凹口的形式展現箱線圖,默認非凹口。
- sym:指定異常點的形狀,默認為+號顯示。
- vert:是否需要將箱線圖垂直擺放,默認垂直擺放。
- whis:指定上下須與上下四分位的距離,默認為1.5倍的四分位差。
- positions:指定箱線圖的位置,默認為[0,1,2…]。
- widths:指定箱線圖的寬度,默認為0.5。
- patch_artist:bool類型參數,是否填充箱體的顏色;默認為False。
- meanline:bool類型參數,是否用線的形式表示均值,默認為False。
- showmeans:bool類型參數,是否顯示均值,默認為False。
- showcaps:bool類型參數,是否顯示箱線圖頂端和末端的兩條線(即上下須),默認為True。
- showbox:bool類型參數,是否顯示箱線圖的箱體,默認為True。
- showfliers:是否顯示異常值,默認為True。
- boxprops:設置箱體的屬性,如邊框色,填充色等。
- labels:為箱線圖添加標簽,類似于圖例的作用。
- filerprops:設置異常值的屬性,如異常點的形狀、大小、填充色等。
- medianprops:設置中位數的屬性,如線的類型、粗細等。
- meanprops:設置均值的屬性,如點的大小、顏色等。
- capprops:設置箱線圖頂端和末端線條的屬性,如顏色、粗細等。
- whiskerprops:設置須的屬性,如顏色、粗細、線的類型等。
# 讀取數據
Sec_Buildings = pd.read_excel(r'D:\PyProject\data\sec_buildings.xlsx')
# 繪制箱線圖
plt.boxplot(x = Sec_Buildings.price_unit, # 指定繪圖數據
patch_artist=True, # 要求用自定義顏色填充盒形圖,默認白色填充
showmeans=True, # 以點的形式顯示均值
boxprops = {'color':'black','facecolor':'steelblue'}, # 設置箱體屬性,如邊框色和填充色
# 設置異常點屬性,如點的形狀、填充色和點的大小
flierprops = {'marker':'o','markerfacecolor':'red', 'markersize':3},
# 設置均值點的屬性,如點的形狀、填充色和點的大小
meanprops = {'marker':'D','markerfacecolor':'indianred', 'markersize':4},
# 設置中位數線的屬性,如線的類型和顏色
medianprops = {'linestyle':'--','color':'orange'},
labels = [''] # 刪除x軸的刻度標簽,否則圖形顯示刻度標簽為1
)
# 添加圖形標題
plt.title('二手房單價分布的箱線圖')
# 顯示圖形
plt.show()
結果:
如圖6-17所示,圖中的上下兩條橫線代表上下須、箱體的上下兩條橫線代表上下四分位數、箱體中的虛線代表中位數、箱體中的點則為均值、上下須兩端的點代表異常值。通過圖中均值和中位數的對比就可以得知數據微微右偏(判斷標準:如果數據近似正態分布,則眾數=中位數=均值;如果數據右偏,則眾數<中位數<均值;如果數值左偏,則眾數>中位數>均值)。 如上繪制的是二手房整體單價的箱線圖,這樣的箱線圖可能并不常見,更多的是分組箱線圖,即二手房的單價按照其他分組變量(如行政區域、樓層、朝向等)進行對比分析。下面繼續使用matplotlib模塊對二手房的單價繪制分組箱線圖,代碼如下:
# 二手房在各行政區域的平均單價
group_region = Sec_Buildings.groupby('region')
avg_price = group_region.aggregate({'price_unit':np.mean}).sort_values('price_unit', ascending = False)
# 通過循環,將不同行政區域的二手房存儲到列表中
region_price = []
for region in avg_price.index:
region_price.append(Sec_Buildings.price_unit[Sec_Buildings.region == region])
# 繪制分組箱線圖
plt.boxplot(x = region_price,
patch_artist=True,
labels = avg_price.index, # 添加x軸的刻度標簽
showmeans=True,
boxprops = {'color':'black', 'facecolor':'steelblue'},
flierprops = {'marker':'o','markerfacecolor':'red', 'markersize':3},
meanprops = {'marker':'D','markerfacecolor':'indianred', 'markersize':4},
medianprops = {'linestyle':'--','color':'orange'}
)
# 添加y軸標簽
plt.ylabel('單價(元)')
# 添加標題
plt.title('不同行政區域的二手房單價對比')
# 顯示圖形
plt.show()
結果:
應用matplotlib模塊繪制如上所示的分組箱線圖會相對煩瑣一些,由于boxplot函數每次只能繪制一個箱線圖,為了能夠實現多個箱線圖的繪制,對數據稍微做了一些變動,即將每個行政區域下的二手房單價匯總到一個列表中,然后基于這個大列表應用boxplot函數。在繪圖過程中,首先做了一個“手腳”,那就是統計各行政區域二手房的平均單價,并降序排序,這樣做的目的就是讓分組箱線圖能夠降序呈現。
雖然pandas模塊中的plot方法可以繪制分組箱線圖,但是該方法是基于數據框執行的,并且數據框的每一列對應一個箱線圖。對于二手房數據集來說,應用plot方法繪制分組箱線圖不太合適,因為每一個行政區的二手房數量不一致,將導致無法重構一個新的數據框用于繪圖。
2.seaborn模塊
如果讀者覺得matplotlib模塊繪制分組箱線圖比較麻煩,可以使用seaborn模塊中的boxplot函數。下面不妨先了解一下該函數的參數含義:
sns.boxplot(x=None, y=None, hue=None, data=None, order=None, hue_order=None, orient=None, color=None, palette=None, saturation=0.75, width=0.8, dodge=True, fliersize=5, linewidth=None, whis=1.5, notch=False, ax=None, **kwargs)
- x:指定箱線圖的x軸數據。
- y:指定箱線圖的y軸數據。
- hue:指定分組變量。
- data:指定用于繪圖的數據集。
- order:傳遞一個字符串列表,用于分類變量的排序。
- hue_order:傳遞一個字符串列表,用于分類變量hue值的排序。
- orient:指定箱線圖的呈現方向,默認為垂直方向。
- color:指定所有箱線圖的填充色。
- palette:指定hue變量的區分色。
- saturation:指定顏色的透明度。
- width:指定箱線圖的寬度。
- dodge:bool類型的參數,當使用hue參數時,是否繪制水平交錯的箱線圖,默認為True。
- fliersize:指定異常值點的大小。
- linewidth:指定箱體邊框的寬度。
- whis:指定上下須與上下四分位的距離,默認為1.5倍的四分位差。
- notch:bool類型的參數,是否繪制凹口箱線圖,默認為False。
- ax:指定子圖的位置。
- **kwargs:關鍵字參數,可以調用plt.boxplot函數中的其他參數。
這里仍以上海二手房數據為例,應用seaborn模塊中的boxplot函數繪制分組箱線圖,詳細代碼如下:
# 繪制分組箱線圖
sns.boxplot(x = 'region', y = 'price_unit', data = Sec_Buildings,
order = avg_price.index, showmeans=True,color = 'steelblue',
flierprops = {'marker':'o','markerfacecolor':'red', 'markersize':3},
meanprops = {'marker':'D','markerfacecolor':'indianred', 'markersize':4},
medianprops = {'linestyle':'--','color':'orange'}
)
# 更改x軸和y軸標簽
plt.xlabel('')
plt.ylabel('單價(元)')
# 添加標題
plt.title('不同行政區域的二手房單價對比')
# 顯示圖形
plt.show()
結果:
通過如上代碼,同樣可以得到完全一致的分組箱線圖。這里建議讀者不要直接學習和使用pandas模塊和seaborn模塊繪制統計圖形,而是先把matplotlib模塊摸透,因為Python的核心繪圖模塊是matplotlib。
6.2.3 小提琴圖
小提琴圖是比較有意思的統計圖形,它將數值型數據的核密度圖與箱線圖融合在一起,進而得到一個形似小提琴的圖形。盡管matplotlib模塊也提供了繪制小提琴圖的函數violinplot,但是繪制出來的圖形中并不包含一個完整的箱線圖,所以本節將直接使用seaborn模塊中的violinplot函數繪制小提琴圖。首先,帶領讀者了解一下有關violinplot函數的語法和參數含義:
sns.violinplot(x=None, y=None, hue=None, data=None, order=None, hue_order=None, bw='scott', cut=2, scale='area', scale_hue=True, gridsize=100, width=0.8, inner='box', split=False, dodge=True, orient=None, linewidth=None, color=None, palette=None, saturation=0.75, ax=None)
- x:指定小提琴圖的x軸數據。
- y:指定小提琴圖的y軸數據。
- hue:指定一個分組變量。
- data:指定繪制小提琴圖的數據集。
- order:傳遞一個字符串列表,用于分類變量的排序。
- hue_order:傳遞一個字符串列表,用于分類變量hue值的排序。
- bw:指定核密度估計的帶寬,帶寬越大,密度曲線越光滑。
- scale:用于調整小提琴圖左右的寬度,如果為area,則表示每個小提琴圖左右部分擁有相同的面積;如果為count,則表示根據樣本數量來調節寬度;如果為width,則表示每個小提琴圖左右兩部分擁有相同的寬度。
- scale_hue:bool類型參數,當使用hue參數時,是否對hue變量的每個水平做標準化處理,默認為True。
- width:使用hue參數時,用于控制小提琴圖的寬度。
- inner:指定小提琴圖內部數據點的形態,如果為box,則表示繪制微型的箱線圖;如果為quartiles,則表示繪制四分位的分布圖;如果為point或stick,則表示繪制點或小豎條。
- split:bool類型參數,使用hue參數時,將小提琴圖從中間分為兩個不同的部分,默認為False。
- dodge:bool類型的參數,當使用hue參數時,是否繪制水平交錯的小提琴圖,默認為True。
- orient:指定小提琴圖的呈現方向,默認為垂直方向。
- linewidth:指定小提琴圖的所有線條寬度。
- color:指定小提琴圖的顏色,該參數與palette參數一起使用時無效。
- palette:指定hue變量的區分色。
- saturation:指定顏色的透明度。
- ax:指定子圖的位置。
接下來,以酒吧的消費數據為例(數據包含客戶的消費金額、消費時間、打賞金額、客戶性別、是否抽煙等字段),利用如上介紹的函數繪制分組小提琴圖,以幫助讀者進一步了解參數的含義,繪圖代碼如下:
# 讀取數據
tips = pd.read_csv(r'D:\PyProject\data\tips.csv')
# 繪制分組小提琴圖
sns.violinplot(x = "total_bill", # 指定x軸的數據
y = "day", # 指定y軸的數據
hue = "sex", # 指定分組變量
data = tips, # 指定繪圖的數據集
order = ['Thur','Fri','Sat','Sun'], # 指定x軸刻度標簽的順序
scale = 'count', # 以男女客戶數調節小提琴圖左右的寬度
split = True, # 將小提琴圖從中間割裂開,形成不同的密度曲線;
palette = 'RdBu' # 指定不同性別對應的顏色(因為hue參數為設置為性別變量)
)
# 添加圖形標題
plt.title('每天不同性別客戶的消費額情況')
# 設置圖例
plt.legend(loc = 'upper center', ncol = 2)
# 顯示圖形
plt.show()
結果:
如圖6-19所示,得到了分組的小提琴圖,讀者會發現,小提琴圖的左右兩邊并不對稱,是因為同時使用了hue參數和split參數,兩邊的核密度圖代表了不同性別客戶的消費額分布。從這張圖中,一共可以反映四個維度的信息,y軸表示客戶的消費額、x軸表示客戶的消費時間、顏色圖例表示客戶的性別、左右核密度圖的寬度代表了樣本量。以周五和周六兩天為例,周五的男女客戶數量差異不大,而周六男性客戶要比女性客戶多得多,那是因為右半邊的核密度圖更寬一些。
6.2.4 折線圖
對于時間序列數據而言,一般都會使用折線圖反映數據背后的趨勢。通常折線圖的橫坐標指代日期數據,縱坐標代表某個數值型變量,當然還可以使用第三個離散變量對折線圖進行分組處理。接下來僅使用Python中的matplotlib模塊和pandas模塊實現折線圖的繪制。盡管seaborn模塊中的tsplot函數也可以繪制時間序列的折線圖,但是該函數非常不合理,故不在本節中介紹。
1.matplotlib模塊
折線圖的繪制可以使用matplotlib模塊中的plot函數實現。關于該函數的語法和參數含義如下:
plt.plot(x, y, linestyle, linewidth, color, marker, markersize, markeredgecolor, markerfactcolor, markeredgewidth, label, alpha)
- x:指定折線圖的x軸數據。
- y:指定折線圖的y軸數據。
- linestyle:指定折線的類型,可以是實線、虛線、點虛線、點點線等,默認為實線。
- linewidth:指定折線的寬度。
- marker:可以為折線圖添加點,該參數是設置點的形狀。
- markersize:設置點的大小。
- markeredgecolor:設置點的邊框色。
- markerfactcolor:設置點的填充色。
- markeredgewidth:設置點的邊框寬度。
- label:為折線圖添加標簽,類似于圖例的作用。
為了進一步理解plot函數中的參數含義,這里以某微信公眾號的閱讀人數和閱讀人次為例(數據包含日期、人數和人次三個字段),繪制2017年第四季度微信文章閱讀人數的折線圖,代碼如下:
# 數據讀取
wechat = pd.read_excel(r'D:\PyProject\data\wechat.xlsx')
# 繪制單條折線圖
plt.plot(wechat.Date, # x軸數據
wechat.Counts, # y軸數據
linestyle = '-', # 折線類型
linewidth = 2, # 折線寬度
color = 'steelblue', # 折線顏色
marker = 'o', # 折線圖中添加圓點
markersize = 6, # 點的大小
markeredgecolor='black', # 點的邊框色
markerfacecolor='brown') # 點的填充色
# 添加y軸標簽
plt.ylabel('人數')
# 添加圖形標題
plt.title('每天微信文章閱讀人數趨勢')
# 顯示圖形
plt.show()
結果:
如圖6-20所示,在繪制折線圖的同時,也添加了每個數據對應的圓點。讀者可能會注意到,代碼中折線類型和點類型分別用一個減號-(代表實線)和字母o(代表空心圓點)表示。是否還有其他的表示方法?這里將常用的線型和點型匯總到表6-1和表6-2中。
雖然上面的圖形可以反映有關微信文章閱讀人數的波動趨勢,但是為了進一步改進這個折線圖,還需要解決兩個問題:
- 如何將微信文章的閱讀人數和閱讀人次同時呈現在圖中。
- 對于x軸的刻度標簽,是否可以只保留月份和日期,并且以7天作為間隔。
# 繪制兩條折線圖
# 導入模塊,用于日期刻度的修改
import matplotlib as mpl
# 繪制閱讀人數折線圖
plt.plot(wechat.Date, # x軸數據
wechat.Counts, # y軸數據
linestyle = '-', # 折線類型,實心線
color = 'steelblue', # 折線顏色
label = '閱讀人數'
)
# 繪制閱讀人次折線圖
plt.plot(wechat.Date, # x軸數據
wechat.Times, # y軸數據
linestyle = '--', # 折線類型,虛線
color = 'indianred', # 折線顏色
label = '閱讀人次'
)
# 獲取圖的坐標信息
ax = plt.gca()
# 設置日期的顯示格式
date_format = mpl.dates.DateFormatter("%m-%d")
ax.xaxis.set_major_formatter(date_format)
# 設置x軸顯示多少個日期刻度
# xlocator = mpl.ticker.LinearLocator(10)
# 設置x軸每個刻度的間隔天數
xlocator = mpl.ticker.MultipleLocator(7)
ax.xaxis.set_major_locator(xlocator)
# 為了避免x軸刻度標簽的緊湊,將刻度標簽旋轉45度
plt.xticks(rotation=45)
# 添加y軸標簽
plt.ylabel('人數')
# 添加圖形標題
plt.title('每天微信文章閱讀人數與人次趨勢')
# 添加圖例
plt.legend()
# 顯示圖形
plt.show()
結果:
如圖6-21所示,恰到好處地解決了之前提出的兩個問題。上面的繪圖代碼可以分解為兩個核心部分:
- 運用兩次plot函數分別繪制閱讀人數和閱讀人次的折線圖,最終通過plt.show()將兩條折線呈現在一張圖中。
- 日期型軸刻度的設置,ax變量用來獲取原始狀態的軸屬性,然后基于ax對象修改刻度的顯示方式,一個是僅包含月日的格式,另一個是每7天作為一個間隔。
2.pandas模塊
如果使用pandas模塊繪制折線圖,調用的仍然是plot方法,接下來以2015—2017年上海每天的最高氣溫數據為例,繪制每月平均最高氣溫的三條折線圖,具體代碼如下:
# 讀取天氣數據
weather = pd.read_excel(r'D:\PyProject\data\weather.xlsx')
# 統計每月的平均最高氣溫
data = weather.pivot_table(index = 'month', columns='year', values='high')
# 繪制折線圖
data.plot(kind = 'line',
style = ['-','--',':'] # 設置折線圖的線條類型
)
# 修改x軸和y軸標簽
plt.xlabel('月份')
plt.ylabel('氣溫')
# 添加圖形標題
plt.title('每月平均最高氣溫波動趨勢')
# 顯示圖形
plt.show()
如圖6-22所示,圖中表示的是各年份中每月平均最高氣溫的走勢,雖然繪圖的核心部分(plot過程)很簡單,但是前提需要將原始數據集轉換成可以繪制多條折線圖的格式,即構成三條折線圖的數據分別為數據框的三個字段。為了構造特定需求的數據集,使用了數據框的pivot_table方法,形成一張滿足條件的透視表。圖6-23所示就是數據集轉換的前后對比。
6.3 關系型數據的可視化
前面的兩節內容都是基于獨立的離散變量或數值變量進行的可視化展現。在眾多的可視化圖形中,有一類圖形專門用于探究兩個或三個變量之間的關系。例如,散點圖用于發現兩個數值變量之間的關系,氣泡圖可以展現三個數值變量之間的關系,熱力圖則體現了兩個離散變量之間的組合關系。
本節將使用matplotlib模塊、pandas模塊和seaborn模塊繪制上述所介紹的三種關系型圖形。下面首先了解一下最常用的散點圖是如何繪制的。
6.3.1 散點圖
如果需要研究兩個數值型變量之間是否存在某種關系,例如正向的線性關系,或者是趨勢性的非線性關系,那么散點圖將是最佳的選擇。
1.matplotlib模塊
matplotlib模塊中的scatter函數可以非常方便地繪制兩個數值型變量的散點圖。這里首先將該函數的語法及參數含義寫在下方,以便讀者掌握函數的使用:
scatter(x, y, s=20, c=None, marker='o', cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, edgecolors=None)
x:指定散點圖的x軸數據。 y:指定散點圖的y軸數據。 s:指定散點圖點的大小,默認為20,通過傳入其他數值型變量,可以實現氣泡圖的繪制。 c:指定散點圖點的顏色,默認為藍色,也可以傳遞其他數值型變量,通過cmap參數的色階表示數值大小。 marker:指定散點圖點的形狀,默認為空心圓。 cmap:指定某個Colormap值,只有當c參數是一個浮點型數組時才有效。 norm:設置數據亮度,標準化到0~1,使用該參數仍需要參數c為浮點型的數組。 vmin、vmax:亮度設置,與norm類似,如果使用norm參數,則該參數無效。 alpha:設置散點的透明度。 linewidths:設置散點邊界線的寬度。 edgecolors:設置散點邊界線的顏色。
下面以iris數據集為例,探究如何應用matplotlib模塊中的scatter函數繪制花瓣寬度與長度之間的散點圖,繪圖代碼如下:
# 讀入數據
iris = pd.read_csv(r'D:\PyProject\data\iris.csv')
# 繪制散點圖
plt.scatter(x = iris.Petal_Width, # 指定散點圖的x軸數據
y = iris.Petal_Length, # 指定散點圖的y軸數據
color = 'steelblue' # 指定散點圖中點的顏色
)
# 添加x軸和y軸標簽
plt.xlabel('花瓣寬度')
plt.ylabel('花瓣長度')
# 添加標題
plt.title('鳶尾花的花瓣寬度與長度關系')
# 顯示圖形
plt.show()
結果:
如圖6-24所示,通過scatter函數就可以非常簡單地繪制出花瓣寬度與長度的散點圖。如果使用pandas模塊中的plot方法,同樣可以很簡單地繪制出散點圖。
2.pandas模塊
# Pandas模塊繪制散點圖
# 繪制散點圖
iris.plot(x = 'Petal_Width', y = 'Petal_Length', kind = 'scatter', title = '鳶尾花的花瓣寬度與長度關系')
# 修改x軸和y軸標簽
plt.xlabel('花瓣寬度')
plt.ylabel('花瓣長度')
# 顯示圖形
plt.show()
結果:
盡管使用這兩個模塊都可以非常方便地繪制出散點圖,但是繪制分組散點圖會稍微復雜一點。如果讀者使用seaborn模塊中的lmplot函數,那么繪制分組散點圖就太簡單了,而且該函數還可以根據散點圖添加線性擬合線。
3.seaborn模塊
為了使讀者清楚地掌握lmplot函數的使用方法,有必要介紹一下該函數的語法和參數含義:
lmplot(x, y, data, hue=None, col=None, row=None, palette=None, col_wrap=None, size=5, aspect=1, markers='o', sharex=True, sharey=True, hue_order=None, col_order=None, row_order=None, legend=True, legend_out=True, scatter=True, fit_reg=True, ci=95, n_boot=1000, order=1, logistic=False, lowess=False, robust=False, logx=False, x_partial=None, y_partial=None, truncate=False, x_jitter=None, y_jitter=None, scatter_kws=None, line_kws=None)
- x,y:指定x軸和y軸的數據。
- data:指定繪圖的數據集。
- hue:指定分組變量。
- col,row:用于繪制分面圖形,指定分面圖形的列向與行向變量。
- palette:為hue參數指定的分組變量設置顏色。
- col_wrap:設置分面圖形中每行子圖的數量。
- size:用于設置每個分面圖形的高度。
- aspect:用于設置每個分面圖形的寬度,寬度等于size*aspect。
- markers:設置點的形狀,用于區分hue參數指定的變量水平值。
- sharex,sharey:bool類型參數,設置繪制分面圖形時是否共享x軸和y軸,默認為True。 hue_order,col_order,row_order:為hue參數、col參數和row參數指定的分組變量設值水平值順序。
- legend:bool類型參數,是否顯示圖例,默認為True。
- legend_out:bool類型參數,是否將圖例放置在圖框外,默認為True。
- scatter:bool類型參數,是否繪制散點圖,默認為True。 fit_reg:bool類型參數,是否擬合線性回歸,默認為True。
- ci:繪制擬合線的置信區間,默認為95%的置信區間。
- n_boot:為了估計置信區間,指定自助重抽樣的次數,默認為1000次。 order:指定多項式回歸,默認指數為1。
- logistic:bool類型參數,是否擬合邏輯回歸,默認為False。 lowess:bool類型參數,是否擬合局部多項式回歸,默認為False。
- robust:bool類型參數,是否擬合魯棒回歸,默認為False。
- logx:bool類型參數,是否對x軸做對數變換,默認為False。
- x_partial,y_partial:為x軸數據和y軸數據指定控制變量,即排除x_partial和y_partial變量的影響下繪制散點圖。
- truncate:bool類型參數,是否根據實際數據的范圍對擬合線做截斷操作,默認為False。
- x_jitter,y_jitter:為x軸變量或y軸變量添加隨機噪聲,當x軸數據與y軸數據比較密集時,可以使用這兩個參數。
- scatter_kws:設置點的其他屬性,如點的填充色、邊框色、大小等。
- line_kws:設置擬合線的其他屬性,如線的形狀、顏色、粗細等。
該函數的參數雖然比較多,但是大多數情況下讀者只需使用幾個重要的參數,如x、y、hue、data等。接下來仍以iris數據集為例,繪制分組散點圖,繪圖代碼如下:
# seaborn模塊繪制分組散點圖
sns.lmplot(x = 'Petal_Width', # 指定x軸變量
y = 'Petal_Length', # 指定y軸變量
hue = 'Species', # 指定分組變量
data = iris, # 指定繪圖數據集
legend_out = False, # 將圖例呈現在圖框內
truncate=True # 根據實際的數據范圍,對擬合線作截斷操作
)
# 修改x軸和y軸標簽
plt.xlabel('花瓣寬度')
plt.ylabel('花瓣長度')
# 添加標題
plt.title('鳶尾花的花瓣寬度與長度關系')
# 顯示圖形
plt.show()
結果:
如圖6-25所示,lmplot函數不僅可以繪制分組散點圖,還可以對每個組內的散點添加回歸線(圖6-25默認擬合線性回歸線)。分組效果的體現是通過hue參數設置的,如果需要擬合其他回歸線,可以指定lowess參數(局部多項式回歸)、logistic參數(邏輯回歸)、order參數(多項式回歸)和robust參數(魯棒回歸)。
6.3.2 氣泡圖
上一節所介紹的散點圖都是反映兩個數值型變量的關系,如果還想通過散點圖添加第三個數值型變量的信息,一般可以使用氣泡圖。氣泡圖的實質就是通過第三個數值型變量控制每個散點的大小,點越大,代表的第三維數值越高,反之亦然。接下來將會介紹如何通過Python繪制氣泡圖。
在上一節中,應用matplotlib模塊中的scatter函數繪制了散點圖,本節將繼續使用該函數繪制氣泡圖。要實現氣泡圖的繪制,關鍵的參數是s,即散點圖中點的大小,如果將數值型變量傳遞給該參數,就可以輕松繪制氣泡圖了。如果讀者對該函數的參數含義還不是很了解,可以查看上一節中的參數含義說明。
下面以某超市的商品類別銷售數據為例,繪制銷售額、利潤和利潤率之間的氣泡圖,探究三者之間的關系,繪圖代碼如下:
# 讀取數據
Prod_Category = pd.read_excel(r'D:\PyProject\data\SuperMarket.xlsx')
# 將利潤率標準化到[0,1]之間(因為利潤率中有負數),然后加上微小的數值0.001
range_diff = Prod_Category.Profit_Ratio.max()-Prod_Category.Profit_Ratio.min()
Prod_Category['std_ratio'] = (Prod_Category.Profit_Ratio-Prod_Category.Profit_Ratio.min())/range_diff + 0.001
# 繪制辦公用品的氣泡圖
plt.scatter(x = Prod_Category.Sales[Prod_Category.Category == '辦公用品'],
y = Prod_Category.Profit[Prod_Category.Category == '辦公用品'],
s = Prod_Category.std_ratio[Prod_Category.Category == '辦公用品']*1000,
color = 'steelblue', label = '辦公用品', alpha = 0.6
)
# 繪制技術產品的氣泡圖
plt.scatter(x = Prod_Category.Sales[Prod_Category.Category == '技術產品'],
y = Prod_Category.Profit[Prod_Category.Category == '技術產品'],
s = Prod_Category.std_ratio[Prod_Category.Category == '技術產品']*1000,
color = 'indianred' , label = '技術產品', alpha = 0.6
)
# 繪制家具產品的氣泡圖
plt.scatter(x = Prod_Category.Sales[Prod_Category.Category == '家具產品'],
y = Prod_Category.Profit[Prod_Category.Category == '家具產品'],
s = Prod_Category.std_ratio[Prod_Category.Category == '家具產品']*1000,
color = 'black' , label = '家具產品', alpha = 0.6
)
# 添加x軸和y軸標簽
plt.xlabel('銷售額')
plt.ylabel('利潤')
# 添加標題
plt.title('銷售額、利潤及利潤率的氣泡圖')
# 添加圖例
plt.legend()
# 顯示圖形
plt.show()
結果:
如圖6-26所示,應用scatter函數繪制了分組氣泡圖,從圖中可知,辦公用品和家具產品的利潤率波動比較大(因為這兩類圓點大小不均)。從代碼角度來看,繪圖的核心部分是使用三次scatter函數,而且代碼結構完全一樣,如果讀者對for循環掌握得比較好,完全可以使用循環的方式替換三次scatter函數的重復應用。
需要說明的是,如果s參數對應的變量值小于等于0,則對應的氣泡點是無法繪制出來的。這里提供一個解決思路,就是先將該變量標準化為[0,1],再加上一個非常小的值,如0.001。如上代碼所示,最后對s參數擴大500倍的目的就是凸顯氣泡的大小。
遺憾的是,pandas模塊和seaborn模塊中沒有繪制氣泡圖的方法或函數,故這里就不再衍生了。如果讀者確實需要繪制氣泡圖,又覺得matplotlib模塊中的scatter函數用起來比較燦瑣,可以使用Python的bokeh模塊,有關該模塊的詳細內容,可以查看官方文檔。
6.3.3 熱力圖
最后介紹另一種關系型數據的可視化圖形,即熱力圖,有時也稱之為交叉填充表。該圖形最典型的用法就是實現列聯表的可視化,即通過圖形的方式展現兩個離散變量之間的組合關系。讀者可以借助于seaborn模塊中的heatmap函數,完成熱力圖的繪制。按照慣例,首先對該函數的用法及參數含義做如下解釋:
heatmap(data, vmin=None, vmax=None, cmap=None, center=None, annot=None, fmt='.2g', annot_kws=None, linewidths=0, linecolor='white', cbar=True, cbar_kws = None, square=False, xticklabels='auto', yticklabels='auto', mask=None, ax=None)
- data:指定繪制熱力圖的數據集。
- vmin,vmax:用于指定圖例中最小值與最大值的顯示值。
- cmap:指定一個colormap對象,用于熱力圖的填充色。
- center:指定顏色中心值,通過該參數可以調整熱力圖的顏色深淺。
- annot:指定一個bool類型的值或與data參數形狀一樣的數組,如果為True,就在熱力圖的每個單元上顯示數值。
- fmt:指定單元格中數據的顯示格式。
- annot_kws:有關單元格中數值標簽的其他屬性描述,如顏色、大小等。
- linewidths:指定每個單元格的邊框寬度。
- linecolor:指定每個單元格的邊框顏色。
- cbar:bool類型參數,是否用顏色條作為圖例,默認為True。
- square:bool類型參數,是否使熱力圖的每個單元格為正方形,默認為False。
- cbar_kws:有關顏色條的其他屬性描述。
- xticklabels,yticklabels:指定熱力圖x軸和y軸的刻度標簽,如果為True,則分別以數據框的變量名和行名稱作為刻度標簽。
- mask:用于突出顯示某些數據。
- ax:用于指定子圖的位置。
接下來,以某服裝店的交易數據為例,統計2009—2012年每個月的銷售總額,然后運用如上介紹的heatmap函數對統計結果進行可視化展現,具體代碼如下:
# 讀取數據
Sales = pd.read_excel(r'D:\PyProject\data\Sales.xlsx')
# 根據交易日期,衍生出年份和月份字段
Sales['year'] = Sales.Date.dt.year
Sales['month'] = Sales.Date.dt.month
# 統計每年各月份的銷售總額
Summary = Sales.pivot_table(index = 'month', columns = 'year', values = 'Sales', aggfunc = np.sum)
# 繪制熱力圖
sns.heatmap(data = Summary, # 指定繪圖數據
cmap = 'PuBuGn', # 指定填充色
linewidths = .1, # 設置每個單元格邊框的寬度
annot = True, # 顯示數值
fmt = '.1e' # 以科學計算法顯示數據
)
#添加標題
plt.title('每年各月份銷售總額熱力圖')
# 顯示圖形
plt.show()
如表6-3所示,它是列聯表的格式,反映的是每年各月份的銷售總額。很顯然,通過肉眼是無法迅速發現銷售業績在各月份中的差異的,如果將數據表以熱力圖的形式展現,問題就會簡單很多。
如圖6-27所示就是將表格進行可視化的結果,每個單元格顏色的深淺代表數值的高低,通過顏色就能迅速發現每年各月份銷售情況的好壞。
6.4 多個圖形的合并
工作中往往會根據業務需求,將繪制的多個圖形組合到一個大圖框內,形成類似儀表板的效果。針對這種情況,如何應用Python將前面所學的各種圖形匯總到一個圖表中,這將是本節所要學習的重點。
關于多種圖形的組合,可以使用matplotlib模塊中的subplot2grid函數。這個函數的靈活性非常高,構成的組合圖既可以是m×n的矩陣風格,也可以是跨行或跨列的矩陣風格。接下來,對該函數的用法和參數含義加以說明:
subplot2grid(shape, loc, rowspan=1, colspan=1, **kwargs)
- shape:指定組合圖的框架形狀,以元組形式傳遞,如2×3的矩陣可以表示成(2,3)。
- loc:指定子圖所在的位置,如shape中第一行第一列可以表示成(0,0)。
- rowspan:指定某個子圖需要跨幾行。
- colspan:指定某個子圖需要跨幾列。
為了使讀者理解函數中的四個參數,這里以2×3的組圖布局為例,說明子圖位置與跨行、跨列的概念,如圖6-28所示。
這兩種布局的前提都需要設置shape參數為(2,3),所不同的是,左圖一共需要布置6個圖形;右圖只需要布置4個圖形,其中第三列跨了兩行(rowspan需要指定為2),第二行跨了兩列(colspan需要指定為2)。圖框中的元組值代表了子圖的位置。接下來以某集市商品交易數據為例,繪制含跨行和跨列的組合圖,代碼如下:
# 讀取數據
Prod_Trade = pd.read_excel(r'D:\PyProject\data\Prod_Trade.xlsx')
# 衍生出交易年份和月份字段
Prod_Trade['year'] = Prod_Trade.Date.dt.year
Prod_Trade['month'] = Prod_Trade.Date.dt.month
# 設置大圖框的長和高
plt.figure(figsize = (12,6))
# 設置第一個子圖的布局
ax1 = plt.subplot2grid(shape = (2,3), loc = (0,0))
# 統計2012年各訂單等級的數量
Class_Counts = Prod_Trade.Order_Class[Prod_Trade.year == 2012].value_counts()
Class_Percent = Class_Counts/Class_Counts.sum()
# 將餅圖設置為圓形(否則有點像橢圓)
ax1.set_aspect(aspect = 'equal')
# 繪制訂單等級餅圖
ax1.pie(x = Class_Percent.values, labels = Class_Percent.index, autopct = '%.1f%%')
# 添加標題
ax1.set_title('各等級訂單比例')
# 設置第二個子圖的布局
ax2 = plt.subplot2grid(shape = (2,3), loc = (0,1))
# 統計2012年每月銷售額
Month_Sales = Prod_Trade[Prod_Trade.year == 2012].groupby(by = 'month').aggregate({'Sales':np.sum})
# 繪制銷售額趨勢圖
Month_Sales.plot(title = '2012年各月銷售趨勢', ax = ax2, legend = False)
# 刪除x軸標簽
ax2.set_xlabel('')
# 設置第三個子圖的布局
ax3 = plt.subplot2grid(shape = (2,3), loc = (0,2), rowspan = 2)
# 繪制各運輸方式的成本箱線圖
sns.boxplot(x = 'Transport', y = 'Trans_Cost', data = Prod_Trade, ax = ax3)
# 添加標題
ax3.set_title('各運輸方式成本分布')
# 刪除x軸標簽
ax3.set_xlabel('')
# 修改y軸標簽
ax3.set_ylabel('運輸成本')
# 設置第四個子圖的布局
ax4 = plt.subplot2grid(shape = (2,3), loc = (1,0), colspan = 2)
# 2012年客單價分布直方圖
sns.distplot(Prod_Trade.Sales[Prod_Trade.year == 2012], bins = 40, norm_hist = True, ax = ax4, hist_kws = {'color':'steelblue'}, kde_kws=({'linestyle':'--', 'color':'red'}))
# 添加標題
ax4.set_title('2012年客單價分布圖')
# 修改x軸標簽
ax4.set_xlabel('銷售額')
# 調整子圖之間的水平間距和高度間距
plt.subplots_adjust(hspace=0.6, wspace=0.3)
# 圖形顯示
plt.show()
結果:
如圖6-29所示,構成了2×3風格的組合圖,其中兩幅子圖是跨行和跨列的,而且這里特地選了matplotlib模塊、pandas模塊和seabron模塊繪制子圖,目的是讓讀者能夠掌握不同模塊圖形的組合。針對如上代碼,需要講解幾個重要的知識點:
- 在繪制每一幅子圖之前,都需要運用subplot2grid函數控制子圖的位置,并傳遞給一個變量對象(如代碼中的ax1、ax2等)。
- 為了使子圖位置(ax1、ax2等)產生效果,不同的繪圖模塊需要應用不同的方法。如果通過matplotlib模塊繪制子圖,則必須使用ax1.plot_function的代碼語法(如上代碼中,繪制餅圖的過程);如果通過pandas模塊或seaborn模塊繪制子圖,則需要為繪圖“方法”或函數指定ax參數(如上代碼中,繪制折線圖、直方圖和箱線圖的過程)。
- 如果為子圖添加標題、坐標軸標簽、刻度值標簽等,不能直接使用plt.title、plt.xlabel、plt.xticks等函數,而是換成ax1.set_*的形式(可參考如上代碼中對子圖標題、坐標軸標簽的設置)。
- 由于子圖之間的默認寬間距和高間距不太合理,故需要通過subplots_adjust函數重新修改子圖之間的水平間距和垂直間距(如倒數第二行代碼所示)。
6.5 本章小結
本章的主題是關于數據的可視化,通過每一個具體的案例介紹了有關matplotlib模塊、pandas模塊和seaborn模塊的繪圖函數和參數含義,分別針對離散型數據、數值型數據和關系型數據講解了最為常用的可視化圖形,包括餅圖、條形圖、直方圖、核密度曲線、箱線圖、小提琴圖、折線圖、散點圖、氣泡圖和熱力圖。最后,借助于subplot2grid函數實現各種模塊下圖形的組合。
通過Python完成數據可視化的模塊還有很多種,例如ggplot、bokeh、pygal、plotly等,讀者可以前往各自的官網查看詳細的文檔說明,相信讀者也會喜歡上其中的幾個模塊。需要注意的是,Python繪圖的核心模塊是matplotlib,其他模塊的繪圖多多少少都會依賴于該模塊,所以讀者一定要牢牢掌握matplotlib模塊中的重要知識點。
本章一共講解了10種常用的統計圖形,為了使讀者方便記憶這些繪圖函數和“方法”,特將本文涉及的繪圖函數匯總如下:
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
