日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

第六章Python數(shù)據(jù)可視化

系統(tǒng) 3823 0

前言

文不如字,字不如表,表不如圖”,說(shuō)的就是可視化的重要性。從事與數(shù)據(jù)相關(guān)的工作者經(jīng)常會(huì)作一些總結(jié)或展望性的報(bào)告,如果報(bào)告中密密麻麻都是文字,相信聽(tīng)眾或者老板一定會(huì)厭煩;如果報(bào)告中呈現(xiàn)的是大量的圖形化結(jié)果,就會(huì)受到眾人的喜愛(ài),因?yàn)閳D形更加直觀、醒目。
本章內(nèi)容的重點(diǎn)就是利用Python繪制常見(jiàn)的統(tǒng)計(jì)圖形,例如條形圖、餅圖、直方圖、折線圖、散點(diǎn)圖等,通過(guò)這些常用圖形的展現(xiàn),將復(fù)雜的數(shù)據(jù)簡(jiǎn)單化。這些圖形的繪制可以通過(guò)matplotlib模塊、pandas模塊或者seaborn模塊實(shí)現(xiàn)。通過(guò)本章內(nèi)容的學(xué)習(xí),讀者將會(huì)掌握以下幾個(gè)方面的知識(shí)點(diǎn):

  • 離散型數(shù)據(jù)都有哪些可用的可視化方法;
  • 數(shù)值型的單變量可用哪些圖形展現(xiàn);
  • 多維數(shù)值之間的關(guān)系表達(dá);
  • 如何將多個(gè)圖形繪制到一個(gè)畫(huà)框內(nèi)。

6.1 離散型變量的可視化

如果你需要使用數(shù)據(jù)可視化的方法來(lái)表達(dá)離散型變量的分布特征,例如統(tǒng)計(jì)某APP用戶的性別比例、某產(chǎn)品在各區(qū)域的銷(xiāo)售量分布、各年齡段內(nèi)男女消費(fèi)者的消費(fèi)能力差異等。對(duì)于類(lèi)似這些離散型變量的統(tǒng)計(jì)描述,可以使用餅圖或者條形圖對(duì)其進(jìn)行展現(xiàn)。接下來(lái),通過(guò)具體的案例來(lái)學(xué)習(xí)餅圖和條形圖的繪制,進(jìn)而掌握Python的繪圖技能。

6.1.1 餅圖
餅圖屬于最傳統(tǒng)的統(tǒng)計(jì)圖形之一(1801年由William Playfair首次發(fā)布使用),它幾乎隨處可見(jiàn),例如大型公司的屏幕墻、各種年度論壇的演示稿以及各大媒體發(fā)布的數(shù)據(jù)統(tǒng)計(jì)報(bào)告等。
首先,需要讀者了解有關(guān)餅圖的原理。餅圖是將一個(gè)圓分割成不同大小的楔形,而圓中的每一個(gè)楔形代表了不同的類(lèi)別值,通常會(huì)根據(jù)楔形的面積大小來(lái)判斷類(lèi)別值的差異。如圖6-1所示,就是一個(gè)由不同大小的楔形組成的餅圖。
第六章Python數(shù)據(jù)可視化_第1張圖片
對(duì)于這樣的餅圖,該如何通過(guò)Python完成圖形的繪制呢?其實(shí)很簡(jiǎn)單,通過(guò)matplotlib模塊和pandas模塊都可以非常方便地得到一個(gè)漂亮的餅圖。下面舉例說(shuō)明如何利用Python實(shí)現(xiàn)餅圖的繪制。

1.matplotlib模塊
如果你選擇matplotlib模塊繪制餅圖的話,首先需要導(dǎo)入該模塊的子模塊pyplot,然后調(diào)用模塊中的pie函數(shù)。關(guān)于該函數(shù)的語(yǔ)法和參數(shù)含義如下:

              
                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:指定繪圖的數(shù)據(jù)。
  • explode:指定餅圖某些部分的突出顯示,即呈現(xiàn)爆炸式。
  • labels:為餅圖添加標(biāo)簽說(shuō)明,類(lèi)似于圖例說(shuō)明。
  • colors:指定餅圖的填充色。
  • autopct:自動(dòng)添加百分比顯示,可以采用格式化的方法顯示。
  • pctdistance:設(shè)置百分比標(biāo)簽與圓心的距離。
  • shadow:是否添加餅圖的陰影效果。
  • labeldistance:設(shè)置各扇形標(biāo)簽(圖例)與圓心的距離。
  • startangle:設(shè)置餅圖的初始擺放角度。 radius:設(shè)置餅圖的半徑大小。
  • counterclock:是否讓餅圖按逆時(shí)針順序呈現(xiàn)。
  • wedgeprops:設(shè)置餅圖內(nèi)外邊界的屬性,如邊界線的粗細(xì)、顏色等。
  • textprops:設(shè)置餅圖中文本的屬性,如字體大小、顏色等。
  • center:指定餅圖的中心點(diǎn)位置,默認(rèn)為原點(diǎn)。
  • frame:是否要顯示餅圖背后的圖框,如果設(shè)置為T(mén)rue的話,需要同時(shí)控制圖框x軸、y軸的范圍和餅圖的中心位置。

該函數(shù)的參數(shù)雖然比較多,但是應(yīng)用起來(lái)非常靈活,而且繪制的餅圖也比較好看。下面以“芝麻信用”失信用戶數(shù)據(jù)為例(數(shù)據(jù)來(lái)源于財(cái)新網(wǎng)),分析近300萬(wàn)失信人群的學(xué)歷分布,pie函數(shù)繪制餅圖的詳細(xì)代碼如下:

            
              # 餅圖的繪制
# 導(dǎo)入第三方模塊
import matplotlib.pyplot as plt

# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用來(lái)正常顯示中文標(biāo)簽
plt.rcParams['axes.unicode_minus'] = False  # 用來(lái)正常顯示負(fù)號(hào)
# 構(gòu)造數(shù)據(jù)
edu = [0.2515,0.3724,0.3336,0.0368,0.0057]
labels = ['中專(zhuān)','大專(zhuān)','本科','碩士','其他']

# 繪制餅圖
plt.pie(x = edu, # 繪圖數(shù)據(jù)
        labels=labels, # 添加教育水平標(biāo)簽
        autopct='%.1f%%' # 設(shè)置百分比的格式,這里保留一位小數(shù)
       )
# 添加圖標(biāo)題
plt.title('失信用戶的教育水平分布')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第2張圖片
圖6-2所示就是一個(gè)不加任何修飾的餅圖。這里只給pie函數(shù)傳遞了三個(gè)核心參數(shù),即繪圖的數(shù)據(jù)、每個(gè)數(shù)據(jù)代表的含義(學(xué)歷標(biāo)簽)以及給餅圖添加數(shù)值標(biāo)簽。很顯然,這樣的餅圖并不是很完美,例如餅圖看上去并不成正圓、餅圖沒(méi)有對(duì)應(yīng)的標(biāo)題、沒(méi)有突出顯示餅圖中的某個(gè)部分等。下面進(jìn)一步對(duì)該餅圖做一些修飾,盡可能讓餅圖看起來(lái)更加舒服,代碼如下:

            
              # 添加修飾的餅圖 
explode = [0,0.1,0,0,0]  # 生成數(shù)據(jù),用于突出顯示大專(zhuān)學(xué)歷人群
colors=['#9999ff','#ff9999','#7777aa','#2442aa','#dd5555']  # 自定義顏色

# 中文亂碼和坐標(biāo)軸負(fù)號(hào)的處理
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 將橫、縱坐標(biāo)軸標(biāo)準(zhǔn)化處理,確保餅圖是一個(gè)正圓,否則為橢圓
plt.axes(aspect='equal')
# 繪制餅圖
plt.pie(x = edu, # 繪圖數(shù)據(jù)
        explode=explode, # 突出顯示大專(zhuān)人群
        labels=labels, # 添加教育水平標(biāo)簽
        colors=colors, # 設(shè)置餅圖的自定義填充色
        autopct='%.1f%%', # 設(shè)置百分比的格式,這里保留一位小數(shù)
        pctdistance=0.8,  # 設(shè)置百分比標(biāo)簽與圓心的距離
        labeldistance = 1.1, # 設(shè)置教育水平標(biāo)簽與圓心的距離
        startangle = 180, # 設(shè)置餅圖的初始角度
        radius = 1.2, # 設(shè)置餅圖的半徑
        counterclock = False, # 是否逆時(shí)針,這里設(shè)置為順時(shí)針?lè)较?        wedgeprops = {'linewidth': 1.5, 'edgecolor':'green'},# 設(shè)置餅圖內(nèi)外邊界的屬性值
        textprops = {'fontsize':10, 'color':'black'}, # 設(shè)置文本標(biāo)簽的屬性值
        )

# 添加圖標(biāo)題
plt.title('失信用戶的受教育水平分布')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第3張圖片
如上呈現(xiàn)的餅圖,直觀上要比之前的餅圖好看很多,這些都是基于pie函數(shù)的靈活參數(shù)所實(shí)現(xiàn)的。餅圖中突出顯示大專(zhuān)學(xué)歷的人群,是因?yàn)樵谶@300萬(wàn)失信人群中,大專(zhuān)學(xué)歷的人數(shù)比例最高,該功能就是通過(guò)explode參數(shù)完成的。另外,還需要對(duì)如上餅圖的繪制說(shuō)明幾點(diǎn):

  • 如果繪制的圖形中涉及中文及數(shù)字中的負(fù)號(hào),都需要通過(guò)rcParams進(jìn)行控制。
  • 由于不加修飾的餅圖更像是一個(gè)橢圓,所以需要pyplot模塊中的axes函數(shù)將橢圓強(qiáng)制為正圓。
  • 自定義顏色的設(shè)置,既可以使用十六進(jìn)制的顏色,也可以使用具體的顏色名稱(chēng),如red、black等。
  • 如果需要添加圖形的標(biāo)題,需要調(diào)用pyplot模塊中的title函數(shù)。
  • 代碼plt.show()用來(lái)呈現(xiàn)最終的圖形,無(wú)論是使用Jupyter或Pycharm編輯器,都需要使用這行代碼呈現(xiàn)圖形。

2.pandas模塊
細(xì)心的讀者一定會(huì)發(fā)現(xiàn),在前面的幾個(gè)章節(jié)中或多或少地應(yīng)用到pandas模塊的繪圖“方法”plot,該方法可以針對(duì)序列和數(shù)據(jù)框繪制常見(jiàn)的統(tǒng)計(jì)圖形,例如折線圖、條形圖、直方圖、箱線圖、核密度圖等。同樣,plot也可以繪制餅圖,接下來(lái)簡(jiǎn)單介紹一下該方法針對(duì)序列的應(yīng)用和參數(shù)含義:

              
                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:指定一個(gè)字符串值,用于繪制圖形的類(lèi)型,默認(rèn)為折線圖line。還可以繪制垂直條形圖bar、水平條形圖hbar、直方圖hist、箱線圖box、核密度圖kde、面積圖area和餅圖pie。
  • ax:控制當(dāng)前子圖在組圖中的位置。例如,在一個(gè)2×2的圖形矩陣中,通過(guò)該參數(shù)控制當(dāng)前圖形在矩陣中的位置。
  • figsize:控制圖形的寬度和高度,以元組形式傳遞,即(width,hright)。
  • use_index:bool類(lèi)型的參數(shù),是否將序列的行索引用作x軸的刻度,默認(rèn)為T(mén)rue。
  • title:用以添加圖形的標(biāo)題。
  • grid:bool類(lèi)型的參數(shù),是否給圖形添加網(wǎng)格線,默認(rèn)為False。
  • legend:bool類(lèi)型的參數(shù),是否添加子圖的圖例,默認(rèn)為False。
  • style:如果kind為line,該參數(shù)可以控制折線圖的線條類(lèi)型。
  • logx:bool類(lèi)型的參數(shù),是否對(duì)x軸做對(duì)數(shù)變換,默認(rèn)為False。
  • logy:bool類(lèi)型的參數(shù),是否對(duì)y軸做對(duì)數(shù)變換,默認(rèn)為False。
  • loglog:bool類(lèi)型的參數(shù),是否同時(shí)對(duì)x軸和y軸做對(duì)數(shù)變換,默認(rèn)為False。
  • xticks:用于設(shè)置x軸的刻度值。 yticks:用于設(shè)置y軸的刻度值。
  • xlim:以元組或列表的形式,設(shè)置x軸的取值范圍,如(0,3)表示x軸落在0~3的范圍之內(nèi)。
  • ylim:以元組或列表的形式,設(shè)置y軸的取值范圍。 rot:接受一個(gè)整數(shù)值,用于旋轉(zhuǎn)刻度值的角度。
  • fontsize:接受一個(gè)整數(shù),用于控制x軸與y軸刻度值的字體大小。
  • colormap:接受一個(gè)表示顏色含義的字符串,或者Python的色彩映射對(duì)象,該參數(shù)用于設(shè)置圖形的區(qū)域顏色。
  • table:該參數(shù)如果為T(mén)rue,表示在繪制圖形的基礎(chǔ)上再添加數(shù)據(jù)表;如果傳遞的是序列或數(shù)據(jù)框,則根據(jù)數(shù)據(jù)添加數(shù)據(jù)表。
  • yerr:如果kind為bar或hbar,該參數(shù)表示在條形圖的基礎(chǔ)上添加誤差棒。
  • xerr:含義同yerr參數(shù)。
  • label:用于添加圖形的標(biāo)簽。
  • secondary_y:bool類(lèi)型的參數(shù),是否添加第二個(gè)y軸,默認(rèn)為False。
  • **kwds:關(guān)鍵字參數(shù),該參數(shù)可以根據(jù)不同的kind值,為圖形添加更多的修飾性參數(shù)(依賴于pyplot中的繪圖函數(shù))。

pandas模塊中的plot“方法”可以根據(jù)kind參數(shù)繪制不同的統(tǒng)計(jì)圖形,而且也包含了其他各種靈活的參數(shù)。除此,根據(jù)不同的kind參數(shù)值,可以調(diào)用更多對(duì)應(yīng)的關(guān)鍵字參數(shù)**kwds,這些關(guān)鍵字參數(shù)都源于pyplot中的繪圖函數(shù)。
為了幫助讀者更好地理解plot方法繪制的統(tǒng)計(jì)圖形,這里仍然以失信用戶數(shù)據(jù)為例,繪制學(xué)歷的分布餅圖,詳細(xì)代碼如下:

            
              # 導(dǎo)入第三方模塊
import pandas as pd
# 構(gòu)建序列
data1 = pd.Series({'中專(zhuān)':0.2515,'大專(zhuān)':0.3724,'本科':0.3336,'碩士':0.0368,'其他':0.0057})
# 將序列的名稱(chēng)設(shè)置為空字符,否則繪制的餅圖左邊會(huì)出現(xiàn)None這樣的字眼
data1.name = ''
# 控制餅圖為正圓
plt.axes(aspect = 'equal')
# plot方法對(duì)序列進(jìn)行繪圖
data1.plot(kind = 'pie', # 選擇圖形類(lèi)型
           autopct='%.1f%%', # 餅圖中添加數(shù)值標(biāo)簽
           radius = 1, # 設(shè)置餅圖的半徑
           startangle = 180, # 設(shè)置餅圖的初始角度
           counterclock = False, # 將餅圖的順序設(shè)置為順時(shí)針?lè)较?           title = '失信用戶的受教育水平分布', # 為餅圖添加標(biāo)題
           wedgeprops = {'linewidth': 1.5, 'edgecolor':'green'}, # 設(shè)置餅圖內(nèi)外邊界的屬性值
           textprops = {'fontsize':10, 'color':'black'} # 設(shè)置文本標(biāo)簽的屬性值
          )
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第4張圖片
如圖6-4所示,應(yīng)用pandas模塊中的plot方法,也可以得到一個(gè)比較好看的餅圖。該方法中除了kind參數(shù)和title參數(shù)屬于plot方法,其他參數(shù)都是pyplot模塊中pie函數(shù)的參數(shù),并且以關(guān)鍵字參數(shù)的形式調(diào)用。

6.1.2 條形圖
雖然餅圖可以很好地表達(dá)離散型變量在各水平上的差異(如會(huì)員的性別比例、學(xué)歷差異、等級(jí)高低等),但是其不擅長(zhǎng)對(duì)比差異不大或水平值過(guò)多的離散型變量,因?yàn)轱瀳D是通過(guò)各楔形面積的大小來(lái)表示數(shù)值的高低,而人類(lèi)對(duì)扇形面積的比較并不是特別敏感。如果讀者手中的數(shù)據(jù)恰好不適合用餅圖展現(xiàn),可以選擇另一種常用的可視化方法,即條形圖。
以垂直條形圖為例,離散型變量在各水平上的差異就是比較柱形的高低,柱體越高,代表的數(shù)值越大,反之亦然。在Python中,可以借助matplotlib、pandas和seaborn模塊完成條形圖的繪制。下面將采用這三個(gè)模塊繪制條形圖。

1.matplotlib模塊
應(yīng)用matplotlib模塊繪制條形圖,需要調(diào)用bar函數(shù),關(guān)于該函數(shù)的語(yǔ)法和參數(shù)含義如下:

              
                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:傳遞數(shù)值序列,指定條形圖中x軸上的刻度值。
  • height:傳遞數(shù)值序列,指定條形圖y軸上的高度。
  • width:指定條形圖的寬度,默認(rèn)為0.8。
  • bottom:用于繪制堆疊條形圖。
  • color:指定條形圖的填充色。
  • edgecolor:指定條形圖的邊框色。
  • linewidth:指定條形圖邊框的寬度,如果指定為0,表示不繪制邊框。
  • tick_label:指定條形圖的刻度標(biāo)簽。
  • xerr:如果參數(shù)不為None,表示在條形圖的基礎(chǔ)上添加誤差棒。
  • yerr:參數(shù)含義同xerr。
  • label:指定條形圖的標(biāo)簽,一般用以添加圖例。
  • ecolor:指定條形圖誤差棒的顏色。
  • align:指定x軸刻度標(biāo)簽的對(duì)齊方式,默認(rèn)為center,表示刻度標(biāo)簽居中對(duì)齊,如果設(shè)置為edge,則表示在每個(gè)條形的左下角呈現(xiàn)刻度標(biāo)簽。
  • log:bool類(lèi)型參數(shù),是否對(duì)坐標(biāo)軸進(jìn)行l(wèi)og變換,默認(rèn)為False。
  • **kwargs:關(guān)鍵字參數(shù),用于對(duì)條形圖進(jìn)行其他設(shè)置,如透明度等。

bar函數(shù)的參數(shù)同樣很多,希望讀者能夠認(rèn)真地掌握每個(gè)參數(shù)的含義,以便使用時(shí)得心應(yīng)手。下面將基于該函數(shù)繪制三類(lèi)條形圖,分別是單變量的垂直或水平條形圖、堆疊條形圖和水平交錯(cuò)條形圖。
(1)垂直或水平條形圖
首先來(lái)繪制單個(gè)離散變量的垂直或水平條形圖,數(shù)據(jù)來(lái)源于互聯(lián)網(wǎng),反映的是2017年中國(guó)六大省份的GDP,繪圖代碼如下:

            
              # 條形圖的繪制--垂直條形圖
# 讀入數(shù)據(jù)
GDP = pd.read_excel(r'D:\PyProject\data\Province GDP 2017.xlsx')
# 設(shè)置繪圖風(fēng)格(不妨使用R語(yǔ)言中的ggplot2風(fēng)格)
plt.style.use('ggplot')
# 繪制條形圖
plt.bar(x = range(GDP.shape[0]), # 指定條形圖x軸的刻度值
        height = GDP.GDP, # 指定條形圖y軸的數(shù)值
        tick_label = GDP.Province, # 指定條形圖x軸的刻度標(biāo)簽
        color = 'steelblue', # 指定條形圖的填充色
       )
# 添加y軸的標(biāo)簽
plt.ylabel('GDP(萬(wàn)億)')
# 添加條形圖的標(biāo)題
plt.title('2017年度6個(gè)省份GDP分布')
# 為每個(gè)條形圖添加數(shù)值標(biāo)簽
for x,y in enumerate(GDP.GDP):
    plt.text(x,y+0.1,'%s' %round(y,1),ha='center')
# 顯示圖形    
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第5張圖片
如圖6-5所示,該條形圖比較清晰地反映了6個(gè)省份GDP的差異。針對(duì)如上代碼需要做幾點(diǎn)解釋?zhuān)?

  • 條形圖中灰色網(wǎng)格的背景是通過(guò)代碼plt.style.use(‘ggplot’)實(shí)現(xiàn)的,如果不添加該行代碼,則條形圖為白底背景。
  • 如果添加圖形的x軸或y軸標(biāo)簽,需要調(diào)用pyplot子模塊中的xlab和ylab函數(shù)。
  • 由于bar函數(shù)沒(méi)有添加數(shù)值標(biāo)簽的參數(shù),因此使用for循環(huán)對(duì)每一個(gè)柱體添加數(shù)值標(biāo)簽,使用的核心函數(shù)是pyplot子模塊中的text。該函數(shù)的參數(shù)很簡(jiǎn)單,前兩個(gè)參數(shù)用于定位字符在圖形中的位置,第三個(gè)參數(shù)表示呈現(xiàn)的具體字符值,第四個(gè)參數(shù)為ha,表示字符的水平對(duì)齊方式為居中對(duì)齊。

站在閱讀者的角度來(lái)看,該條形圖可能并不是很理想,因?yàn)椴荒芸焖俚匕l(fā)現(xiàn)哪個(gè)省份GDP最高或最低。如果將該條形圖進(jìn)行降序或升序處理,可能會(huì)更直觀一些。這里就以水平條形圖為例,代碼如下:

            
              # 條形圖的繪制--水平條形圖
# 對(duì)讀入的數(shù)據(jù)作升序排序
GDP.sort_values(by = 'GDP', inplace = True)
# 繪制條形圖
plt.barh(y = range(GDP.shape[0]), # 指定條形圖y軸的刻度值
        width = GDP.GDP, # 指定條形圖x軸的數(shù)值
        tick_label = GDP.Province, # 指定條形圖y軸的刻度標(biāo)簽
        color = 'steelblue', # 指定條形圖的填充色
       )
# 添加x軸的標(biāo)簽
plt.xlabel('GDP(萬(wàn)億)')
# 添加條形圖的標(biāo)題
plt.title('2017年度6個(gè)省份GDP分布')
# 為每個(gè)條形圖添加數(shù)值標(biāo)簽
for y,x in enumerate(GDP.GDP):
    plt.text(x+0.1,y,'%s' %round(x,1),va='center')
# 顯示圖形    
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第6張圖片
圖6-6所示就是經(jīng)過(guò)排序的水平條形圖(實(shí)際上是垂直條形圖的軸轉(zhuǎn)置)。需要注意的是,水平條形圖不再是bar函數(shù),而是barh函數(shù)。讀者可能疑惑,為什么對(duì)原始數(shù)據(jù)做升序排序,但是圖形看上去是降序(從上往下)?那是因?yàn)樗綏l形圖的y軸刻度值是從下往上布置的,所以條形圖從下往上是滿足升序的。

(2)堆疊條形圖
正如前文所介紹的,不管是垂直條形圖還是水平條形圖,都只是反映單個(gè)離散變量的統(tǒng)計(jì)圖形,如果想通過(guò)條形圖傳遞兩個(gè)離散變量的信息該如何做到?相信讀者一定見(jiàn)過(guò)堆疊條形圖,該類(lèi)型條形圖的橫坐標(biāo)代表一個(gè)維度的離散變量,堆疊起來(lái)的“塊”代表了另一個(gè)維度的離散變量。這樣的條形圖,最大的優(yōu)點(diǎn)是可以方便比較累積和,那這種條形圖該如何通過(guò)Python繪制呢?這里以2017年四個(gè)季度的產(chǎn)業(yè)值為例(數(shù)據(jù)來(lái)源于中國(guó)統(tǒng)計(jì)局),繪制堆疊條形圖,詳細(xì)代碼如下:

            
              # 條形圖的繪制--堆疊條形圖
# 讀入數(shù)據(jù)
Industry_GDP = pd.read_excel(r'D:\PyProject\data\Industry_GDP.xlsx')
# 取出四個(gè)不同的季度標(biāo)簽,用作堆疊條形圖x軸的刻度標(biāo)簽
Quarters = Industry_GDP.Quarter.unique()
# 取出第一產(chǎn)業(yè)的四季度值
Industry1 = Industry_GDP.GPD[Industry_GDP.Industry_Type == '第一產(chǎn)業(yè)']
# 重新設(shè)置行索引
Industry1.index = range(len(Quarters))
# 取出第二產(chǎn)業(yè)的四季度值
Industry2 = Industry_GDP.GPD[Industry_GDP.Industry_Type == '第二產(chǎn)業(yè)']
# 重新設(shè)置行索引
Industry2.index = range(len(Quarters))
# 取出第三產(chǎn)業(yè)的四季度值
Industry3 = Industry_GDP.GPD[Industry_GDP.Industry_Type == '第三產(chǎn)業(yè)']

# 繪制堆疊條形圖
# 各季度下第一產(chǎn)業(yè)的條形圖
plt.bar(x = range(len(Quarters)), height=Industry1, color = 'steelblue', label = '第一產(chǎn)業(yè)', tick_label = Quarters)
# 各季度下第二產(chǎn)業(yè)的條形圖
plt.bar(x = range(len(Quarters)), height=Industry2, bottom = Industry1, color = 'green', label = '第二產(chǎn)業(yè)')
# 各季度下第三產(chǎn)業(yè)的條形圖
plt.bar(x = range(len(Quarters)), height=Industry3, bottom = Industry1  + Industry2, color = 'red', label = '第三產(chǎn)業(yè)')
# 添加y軸標(biāo)簽
plt.ylabel('生成總值(億)')
# 添加圖形標(biāo)題
plt.title('2017年各季度三產(chǎn)業(yè)總值')
# 顯示各產(chǎn)業(yè)的圖例
plt.legend()
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第7張圖片
如上就是一個(gè)典型的堆疊條形圖,雖然繪圖的代碼有些偏長(zhǎng),但是其思想還是比較簡(jiǎn)單的,就是分別針對(duì)三種產(chǎn)業(yè)的產(chǎn)值繪制三次條形圖。需要注意的是,第二產(chǎn)業(yè)的條形圖是在第一產(chǎn)業(yè)的基礎(chǔ)上做了疊加,故需要將bottom參數(shù)設(shè)置為Industry1;而第三產(chǎn)業(yè)的條形圖又是疊加在第一和第二產(chǎn)業(yè)之上,所以需要將bottom參數(shù)設(shè)置為Industry1+ Industry2。
讀者可能疑惑,通過(guò)條件判斷將三種產(chǎn)業(yè)的值(Industry1、Industry2、Industry3)分別取出來(lái)后,為什么還要重新設(shè)置行索引?那是因?yàn)楦骷径认旅恳环N產(chǎn)業(yè)值前的行索引都不相同,這就導(dǎo)致無(wú)法進(jìn)行Industry1+ Industry2的和計(jì)算(讀者不妨試試不改變序列Industry1和Industry2的行索引的后果)。

(3)水平交錯(cuò)條形圖 堆疊條形圖可以包含兩個(gè)離散變量的信息,而且可以比較各季度整體產(chǎn)值的高低水平,但是其缺點(diǎn)是不易區(qū)分“塊”之間的差異,例如二、三季度的第三產(chǎn)業(yè)值差異就不是很明顯,區(qū)分高低就相對(duì)困難。而交錯(cuò)條形圖恰好就可以解決這個(gè)問(wèn)題,該類(lèi)型的條形圖就是將堆疊的“塊”水平排開(kāi),如想繪制這樣的條形圖,可以參考下方代碼(數(shù)據(jù)來(lái)源于胡潤(rùn)財(cái)富榜,反映的是5個(gè)城市億萬(wàn)資產(chǎn)超高凈值家庭數(shù)):

            
              # 條形圖的繪制--水平交錯(cuò)條形圖
# 導(dǎo)入第三方模塊
import numpy as np
# 讀入數(shù)據(jù)
HuRun = pd.read_excel(r'D:\PyProject\data\HuRun.xlsx')
# 取出城市名稱(chēng)
Cities = HuRun.City.unique()
# 取出2016年各城市億萬(wàn)資產(chǎn)家庭數(shù)
Counts2016 = HuRun.Counts[HuRun.Year == 2016]
# 取出2017年各城市億萬(wàn)資產(chǎn)家庭數(shù)
Counts2017 = HuRun.Counts[HuRun.Year == 2017]

# 繪制水平交錯(cuò)條形圖
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)
# 添加刻度標(biāo)簽(向右偏移0.225)
plt.xticks(np.arange(5)+0.2, Cities)
# 添加y軸標(biāo)簽
plt.ylabel('億萬(wàn)資產(chǎn)家庭數(shù)')
# 添加圖形標(biāo)題
plt.title('近兩年5個(gè)城市億萬(wàn)資產(chǎn)家庭數(shù)比較')
# 添加圖例
plt.legend()
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第8張圖片
圖6-8反映的是2016年和2017年5大城市億萬(wàn)資產(chǎn)家庭數(shù)的條形圖,可以很好地比較不同年份下的差異。例如,這5個(gè)城市中,2017年的億萬(wàn)資產(chǎn)家庭數(shù)較2016年都有所增加。
但是對(duì)于這種數(shù)據(jù),就不適合使用堆疊條形圖,因?yàn)槎询B條形圖可以反映總計(jì)的概念。如果將2016年和2017年億萬(wàn)資產(chǎn)家庭數(shù)堆疊計(jì)總,就會(huì)出現(xiàn)問(wèn)題,因?yàn)榇蟛糠旨彝?shù)在這兩年內(nèi)都被重復(fù)統(tǒng)計(jì)在胡潤(rùn)財(cái)富榜中,計(jì)算出來(lái)的總和會(huì)被擴(kuò)大。
另外,再對(duì)如上的代碼做三點(diǎn)解釋?zhuān)M軌驇椭x者解去疑惑:

  • 如上的水平交錯(cuò)條形圖,其實(shí)質(zhì)就是使用兩次bar函數(shù),所不同的是,第二次bar函數(shù)使得條形圖往右偏了0.4個(gè)單位(left=np.arange(len(Cities))+bar_width),進(jìn)而形成水平交錯(cuò)條形圖的效果。
  • 每一個(gè)bar函數(shù),都必須控制條形圖的寬度(width=bar_width),否則會(huì)導(dǎo)致條形圖的重疊。
  • 如果利用bar函數(shù)的tick_label參數(shù)添加條形圖x軸上的刻度標(biāo)簽,會(huì)發(fā)現(xiàn)標(biāo)簽并不是居中對(duì)齊在兩個(gè)條形圖之間,為了克服這個(gè)問(wèn)題,使用了pyplot子模塊中的xticks函數(shù),并且使刻度標(biāo)簽的位置向右移0.2個(gè)單位。

2.pandas模塊
通過(guò)pandas模塊繪制條形圖仍然使用plot方法,該“方法”的語(yǔ)法和參數(shù)含義在前文已經(jīng)詳細(xì)介紹過(guò),但是plot方法存在一點(diǎn)瑕疵,那就是無(wú)法繪制堆疊條形圖。下面通過(guò)該模塊的plot方法繪制單個(gè)離散變量的垂直條形圖或水平條形圖以及兩個(gè)離散變量的水平交錯(cuò)條形圖,代碼如下:

            
              # Pandas模塊之垂直或水平條形圖
# 繪圖(此時(shí)的數(shù)據(jù)集在前文已經(jīng)按各省GDP做過(guò)升序處理)
GDP.GDP.plot(kind = 'bar', width = 0.8, rot = 0, color = 'steelblue', title = '2017年度6個(gè)省份GDP分布')
# 添加y軸標(biāo)簽
plt.ylabel('GDP(萬(wàn)億)')
# 添加x軸刻度標(biāo)簽
plt.xticks(range(len(GDP.Province)), #指定刻度標(biāo)簽的位置  
           GDP.Province # 指出具體的刻度標(biāo)簽值
          )
# 為每個(gè)條形圖添加數(shù)值標(biāo)簽
for x,y in enumerate(GDP.GDP):
    plt.text(x-0.1,y+0.2,'%s' %round(y,1),va='center')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第9張圖片
只要掌握matplotlib模塊繪制單個(gè)離散變量的條形圖方法,就可以套用到pandas模塊中的plot方法,兩者是相通的。讀者可以嘗試plot方法繪制水平條形圖,這里就不再給出參考代碼了。
接下來(lái)使用plot方法繪制含兩個(gè)離散變量的水平交錯(cuò)條形圖,具體代碼如下:

            
              # Pandas模塊之水平交錯(cuò)條形圖
HuRun_reshape = HuRun.pivot_table(index = 'City', columns='Year', values='Counts').reset_index()
# 對(duì)數(shù)據(jù)集降序排序
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, # 用于旋轉(zhuǎn)x軸刻度標(biāo)簽的角度,0表示水平顯示刻度標(biāo)簽
                   width = 0.8, title = '近兩年5個(gè)城市億萬(wàn)資產(chǎn)家庭數(shù)比較')
# 添加y軸標(biāo)簽
plt.ylabel('億萬(wàn)資產(chǎn)家庭數(shù)')
plt.xlabel('')
plt.show()

            
          

第六章Python數(shù)據(jù)可視化_第10張圖片
如上代碼所示,應(yīng)用plot方法繪制水平交錯(cuò)條形圖,必須更改原始數(shù)據(jù)集的形狀,即將兩個(gè)離散型變量的水平值分別布置到行與列中(代碼中采用透視表的方法實(shí)現(xiàn)),最終形成的表格變換如圖6-10所示。
針對(duì)變換后的數(shù)據(jù),可以使用plot方法實(shí)現(xiàn)水平交錯(cuò)條形圖的繪制,從代碼量來(lái)看,要比使用matplotlib模塊簡(jiǎn)短一些,得到的條形圖如圖6-11所示。
第六章Python數(shù)據(jù)可視化_第11張圖片
3.seaborn模塊繪制條形圖
seaborn模塊是一款專(zhuān)門(mén)用于繪制統(tǒng)計(jì)圖形的利器,通過(guò)該模塊寫(xiě)出來(lái)的代碼也是非常通俗易懂的。該模塊并不在Anoconda集成工具中,故需要讀者另行下載。下面就簡(jiǎn)單介紹一下如何通過(guò)該模塊完成條形圖的繪制(同樣無(wú)法繪制堆疊條形圖)。

            
              # seaborn模塊之垂直或水平條形圖
# 導(dǎo)入第三方模塊
import seaborn as sns
sns.barplot(y = 'Province', # 指定條形圖x軸的數(shù)據(jù)
            x = 'GDP', # 指定條形圖y軸的數(shù)據(jù)
            data = GDP, # 指定需要繪圖的數(shù)據(jù)集
            color = 'steelblue', # 指定條形圖的填充色
            orient = 'horizontal' # 將條形圖水平顯示
           )
# 重新設(shè)置x軸和y軸的標(biāo)簽
plt.xlabel('GDP(萬(wàn)億)')
plt.ylabel('')
# 添加圖形的標(biāo)題
plt.title('2017年度6個(gè)省份GDP分布')
# 為每個(gè)條形圖添加數(shù)值標(biāo)簽
for y,x in enumerate(GDP.GDP):
    plt.text(x,y,'%s' %round(x,1),va='center')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第12張圖片
如上代碼就是通過(guò)seaborn模塊中的barplot函數(shù)實(shí)現(xiàn)單個(gè)離散變量的條形圖。除此之外,seaborn模塊中的barplot函數(shù)還可以繪制兩個(gè)離散變量的水平交錯(cuò)條形圖,所以有必要介紹一下該函數(shù)的用法及重要參數(shù)含義:

              
                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軸數(shù)據(jù)。
  • y:指定條形圖的y軸數(shù)據(jù)。 -
  • hue:指定用于分組的另一個(gè)離散變量。
  • data:指定用于繪圖的數(shù)據(jù)集。
  • order:傳遞一個(gè)字符串列表,用于分類(lèi)變量的排序。
  • hur_order:傳遞一個(gè)字符串列表,用于分類(lèi)變量hue值的排序。
  • ci:用于繪制條形圖的誤差棒(置信區(qū)間)。
  • n_boot:當(dāng)指定ci參數(shù)時(shí),可以通過(guò)n_boot參數(shù)控制自助抽樣的迭代次數(shù)。
  • orient:指定水平或垂直條形圖。
  • color:指定所有條形圖所屬的一種填充色。
  • palette:指定hue變量中各水平的顏色。
  • saturation:指定顏色的透明度。
  • errcolor:指定誤差棒的顏色。
  • errwidth:指定誤差棒的線寬。
  • capsize:指定誤差棒兩端線條的長(zhǎng)度。
  • dodge:bool類(lèi)型參數(shù),當(dāng)使用hue參數(shù)時(shí),是否繪制水平交錯(cuò)條形圖,默認(rèn)為T(mén)rue。
  • ax:用于控制子圖的位置。
  • **kwagrs:關(guān)鍵字參數(shù),可以調(diào)用plt.bar函數(shù)中的其他參數(shù)。

為了說(shuō)明如上函數(shù)中的參數(shù),這里以泰坦尼克號(hào)數(shù)據(jù)集為例,繪制水平交錯(cuò)條形圖,代碼如下:

            
              # 讀入數(shù)據(jù)
Titanic = pd.read_csv(r'D:\PyProject\data\titanic_train.csv')
# 繪制水平交錯(cuò)條形圖
sns.barplot(x = 'Pclass', # 指定x軸數(shù)據(jù)
            y = 'Age', # 指定y軸數(shù)據(jù)
            hue = 'Sex', # 指定分組數(shù)據(jù)
            data = Titanic, # 指定繪圖數(shù)據(jù)集
            palette = 'RdBu', # 指定男女性別的不同顏色
            errcolor = 'blue', # 指定誤差棒的顏色
            errwidth=2, # 指定誤差棒的線寬
            saturation = 1, # 指定顏色的透明度,這里設(shè)置為無(wú)透明度
            capsize = 0.05 # 指定誤差棒兩端線條的寬度
           )
# 添加圖形標(biāo)題
plt.title('各船艙等級(jí)中男女乘客的年齡差異')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第13張圖片
如圖6-13所示,繪制的每一個(gè)條形圖中都含有一條豎線,該豎線就是條形圖的誤差棒,即各組別下年齡的標(biāo)準(zhǔn)差大小。從圖6-13可知,三等艙的男性乘客年齡是最為接近的,因?yàn)闃?biāo)準(zhǔn)差最小。
需要注意的是,數(shù)據(jù)集Titanic并非匯總好的數(shù)據(jù),是不可以直接應(yīng)用到matplotlib模塊中的bar函數(shù)與pandas模塊中的plot方法。如需使用,必須先對(duì)數(shù)據(jù)集進(jìn)行分組聚合,關(guān)于分組聚合的內(nèi)容已經(jīng)在第5章中介紹過(guò),讀者可以前去了解。

6.2 數(shù)值型變量的可視化

很多時(shí)候,我們拿到手的數(shù)據(jù)都包含大量的數(shù)值型變量,在對(duì)數(shù)值型變量進(jìn)行探索和分析時(shí),一般都會(huì)應(yīng)用到可視化方法。而本節(jié)的重點(diǎn)就是介紹如何使用Python實(shí)現(xiàn)數(shù)值型變量的可視化,通過(guò)本節(jié)內(nèi)容的學(xué)習(xí),讀者將會(huì)掌握如何使用matplotlib模塊、pandas模塊和seaborn模塊繪制直方圖、核密度圖、箱線圖、小提琴圖、折線圖以及面積圖。

6.2.1 直方圖與核密度曲線
直方圖一般用來(lái)觀察數(shù)據(jù)的分布形態(tài),橫坐標(biāo)代表數(shù)值的均勻分段,縱坐標(biāo)代表每個(gè)段內(nèi)的觀測(cè)數(shù)量(頻數(shù))。一般直方圖都會(huì)與核密度圖搭配使用,目的是更加清晰地掌握數(shù)據(jù)的分布特征,下面將詳細(xì)介紹該類(lèi)型圖形的繪制。

1.matplotlib模塊
matplotlib模塊中的hist函數(shù)就是用來(lái)繪制直方圖的。關(guān)于該函數(shù)的語(yǔ)法及參數(shù)含義如下:

              
                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:指定要繪制直方圖的數(shù)據(jù)。
  • bins:指定直方圖條形的個(gè)數(shù)。
  • range:指定直方圖數(shù)據(jù)的上下界,默認(rèn)包含繪圖數(shù)據(jù)的最大值和最小值。
  • normed:是否將直方圖的頻數(shù)轉(zhuǎn)換成頻率。
  • weights:該參數(shù)可為每一個(gè)數(shù)據(jù)點(diǎn)設(shè)置權(quán)重。
  • cumulative:是否需要計(jì)算累計(jì)頻數(shù)或頻率。
  • bottom:可以為直方圖的每個(gè)條形添加基準(zhǔn)線,默認(rèn)為0。
  • histtype:指定直方圖的類(lèi)型,默認(rèn)為bar,除此之外,還有barstacked、step和stepfilled。
  • align:設(shè)置條形邊界值的對(duì)齊方式,默認(rèn)為mid,另外還有l(wèi)eft和right。
  • orientation:設(shè)置直方圖的擺放方向,默認(rèn)為垂直方向。
  • rwidth:設(shè)置直方圖條形的寬度。
  • log:是否需要對(duì)繪圖數(shù)據(jù)進(jìn)行l(wèi)og變換。
  • color:設(shè)置直方圖的填充色。
  • edgecolor:設(shè)置直方圖邊框色。
  • label:設(shè)置直方圖的標(biāo)簽,可通過(guò)legend展示其圖例。
  • stacked:當(dāng)有多個(gè)數(shù)據(jù)時(shí),是否需要將直方圖呈堆疊擺放,默認(rèn)水平擺放。

這里不妨以Titanic數(shù)據(jù)集為例繪制乘客的年齡直方圖,具體代碼如下:

            
              # matplotlib模塊繪制直方圖
# 檢查年齡是否有缺失
any(Titanic.Age.isnull())
# 不妨刪除含有缺失年齡的觀察
Titanic.dropna(subset=['Age'], inplace=True)
# 繪制直方圖
plt.hist(x = Titanic.Age, # 指定繪圖數(shù)據(jù)
         bins = 20, # 指定直方圖中條塊的個(gè)數(shù)
         color = 'steelblue', # 指定直方圖的填充色
         edgecolor = 'black' # 指定直方圖的邊框色
         )
# 添加x軸和y軸標(biāo)簽
plt.xlabel('年齡')
plt.ylabel('頻數(shù)')
# 添加標(biāo)題
plt.title('乘客年齡分布')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第14張圖片
如圖6-14所示,就是關(guān)于乘客年齡的直方圖分布。需要注意的是,如果原始數(shù)據(jù)集中存在缺失值, 一定要對(duì)缺失觀測(cè)進(jìn)行刪除或替換 ,否則無(wú)法繪制成功。如果在直方圖的基礎(chǔ)上再添加核密度圖,通過(guò)matplotlib模塊就比較吃力了,因?yàn)槭紫鹊糜?jì)算出每一個(gè)年齡對(duì)應(yīng)的核密度值。為了簡(jiǎn)單起見(jiàn),下面利用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軸標(biāo)簽
plt.xlabel('年齡')
plt.ylabel('核密度值')
# 添加標(biāo)題
plt.title('乘客年齡分布')
# 顯示圖例
plt.legend()
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第15張圖片
如圖6-15所示,Python的核心代碼就兩行,分別是利用plot方法繪制直方圖和核密度圖。需要注意的是,在直方圖的基礎(chǔ)上添加核密度圖,必須將直方圖的頻數(shù)更改為頻率,即normed(新版本為density)參數(shù)設(shè)置為T(mén)rue。

3.seaborn模塊
盡管這幅圖滿足了兩種圖形的合成,但其表達(dá)的是所有乘客的年齡分布,如果按性別分組,研究不同性別下年齡分布的差異,該如何實(shí)現(xiàn)?針對(duì)這個(gè)問(wèn)題,使用matplotlib模塊或pandas模塊都會(huì)稍微復(fù)雜一些,推薦使用seaborn模塊中的distplot函數(shù),因?yàn)樵摵瘮?shù)的代碼簡(jiǎn)潔而易懂。關(guān)于該函數(shù)的語(yǔ)法和參數(shù)含義如下:

              
                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:指定繪圖數(shù)據(jù),可以是序列、一維數(shù)組或列表。
  • bins:指定直方圖條形的個(gè)數(shù)。
  • hist:bool類(lèi)型的參數(shù),是否繪制直方圖,默認(rèn)為T(mén)rue。
  • kde:bool類(lèi)型的參數(shù),是否繪制核密度圖,默認(rèn)為T(mén)rue。
  • rug:bool類(lèi)型的參數(shù),是否繪制須圖(如果數(shù)據(jù)比較密集,該參數(shù)比較有用),默認(rèn)為False。
  • fit:指定一個(gè)隨機(jī)分布對(duì)象(需調(diào)用scipy模塊中的隨機(jī)分布函數(shù)),用于繪制隨機(jī)分布的概率密度曲線。
  • hist_kws:以字典形式傳遞直方圖的其他修飾屬性,如填充色、邊框色、寬度等。
  • kde_kws:以字典形式傳遞核密度圖的其他修飾屬性,如線的顏色、線的類(lèi)型等。
  • rug_kws:以字典形式傳遞須圖的其他修飾屬性,如線的顏色、線的寬度等。
  • fit_kws:以字典形式傳遞概率密度曲線的其他修飾屬性,如線條顏色、形狀、寬度等。
  • color:指定圖形的顏色,除了隨機(jī)分布曲線的顏色。
  • vertical:bool類(lèi)型的參數(shù),是否將圖形垂直顯示,默認(rèn)為T(mén)rue。
  • norm_hist:bool類(lèi)型的參數(shù),是否將頻數(shù)更改為頻率,默認(rèn)為False。
  • axlabel:用于顯示軸標(biāo)簽。 label:指定圖形的圖例,需結(jié)合plt.legend()一起使用。
  • ax:指定子圖的位置。

從函數(shù)的參數(shù)可知,通過(guò)該函數(shù),可以實(shí)現(xiàn)三種圖形的合成,分別是直方圖(hist參數(shù))、核密度曲線(kde參數(shù))以及指定的理論分布密度曲線(fit參數(shù))。接下來(lái),針對(duì)如上介紹的distplot函數(shù),繪制不同性別下乘客的年齡分布圖,具體代碼如下:

            
              # 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()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第16張圖片
如圖6-16所示,為了避免四個(gè)圖形混在一起不易發(fā)現(xiàn)數(shù)據(jù)背后的特征,將直方圖與核密度圖分開(kāi)繪制。從直方圖來(lái)看,女性年齡的分布明顯比男性矮,說(shuō)明在各年齡段下,男性乘客要比女性乘客多;再看核密度圖,男女性別的年齡分布趨勢(shì)比較接近,說(shuō)明各年齡段下的男女乘客人數(shù)同步增加或減少。

6.2.2 箱線圖
箱線圖是另一種體現(xiàn)數(shù)據(jù)分布的圖形,通過(guò)該圖可以得知數(shù)據(jù)的下須值(Q1-1.5IQR)、下四分位數(shù)(Q1)、中位數(shù)(Q2)、均值、上四分位(Q3)數(shù)和上須值(Q3+1.5IQR),更重要的是,箱線圖還可以發(fā)現(xiàn)數(shù)據(jù)中的異常點(diǎn)。
箱線圖的繪制仍然可以通過(guò)matplotlib模塊、pandas模塊和seaborn模塊完成,下面將一一介紹各模塊繪制條形圖的過(guò)程。

1.matplotlib模塊
首先介紹一下matplotlib模塊中繪制箱線圖的boxplot函數(shù),有關(guān)該函數(shù)的語(yǔ)法和參數(shù)含義如下:

              
                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:指定要繪制箱線圖的數(shù)據(jù)。
  • notch:是否以凹口的形式展現(xiàn)箱線圖,默認(rèn)非凹口。
  • sym:指定異常點(diǎn)的形狀,默認(rèn)為+號(hào)顯示。
  • vert:是否需要將箱線圖垂直擺放,默認(rèn)垂直擺放。
  • whis:指定上下須與上下四分位的距離,默認(rèn)為1.5倍的四分位差。
  • positions:指定箱線圖的位置,默認(rèn)為[0,1,2…]。
  • widths:指定箱線圖的寬度,默認(rèn)為0.5。
  • patch_artist:bool類(lèi)型參數(shù),是否填充箱體的顏色;默認(rèn)為False。
  • meanline:bool類(lèi)型參數(shù),是否用線的形式表示均值,默認(rèn)為False。
  • showmeans:bool類(lèi)型參數(shù),是否顯示均值,默認(rèn)為False。
  • showcaps:bool類(lèi)型參數(shù),是否顯示箱線圖頂端和末端的兩條線(即上下須),默認(rèn)為T(mén)rue。
  • showbox:bool類(lèi)型參數(shù),是否顯示箱線圖的箱體,默認(rèn)為T(mén)rue。
  • showfliers:是否顯示異常值,默認(rèn)為T(mén)rue。
  • boxprops:設(shè)置箱體的屬性,如邊框色,填充色等。
  • labels:為箱線圖添加標(biāo)簽,類(lèi)似于圖例的作用。
  • filerprops:設(shè)置異常值的屬性,如異常點(diǎn)的形狀、大小、填充色等。
  • medianprops:設(shè)置中位數(shù)的屬性,如線的類(lèi)型、粗細(xì)等。
  • meanprops:設(shè)置均值的屬性,如點(diǎn)的大小、顏色等。
  • capprops:設(shè)置箱線圖頂端和末端線條的屬性,如顏色、粗細(xì)等。
  • whiskerprops:設(shè)置須的屬性,如顏色、粗細(xì)、線的類(lèi)型等。
            
              # 讀取數(shù)據(jù)
Sec_Buildings = pd.read_excel(r'D:\PyProject\data\sec_buildings.xlsx')
# 繪制箱線圖
plt.boxplot(x = Sec_Buildings.price_unit, # 指定繪圖數(shù)據(jù)
            patch_artist=True, # 要求用自定義顏色填充盒形圖,默認(rèn)白色填充
            showmeans=True, # 以點(diǎn)的形式顯示均值
            boxprops = {'color':'black','facecolor':'steelblue'}, # 設(shè)置箱體屬性,如邊框色和填充色
            # 設(shè)置異常點(diǎn)屬性,如點(diǎn)的形狀、填充色和點(diǎn)的大小
            flierprops = {'marker':'o','markerfacecolor':'red', 'markersize':3}, 
            # 設(shè)置均值點(diǎn)的屬性,如點(diǎn)的形狀、填充色和點(diǎn)的大小
            meanprops = {'marker':'D','markerfacecolor':'indianred', 'markersize':4}, 
            # 設(shè)置中位數(shù)線的屬性,如線的類(lèi)型和顏色
            medianprops = {'linestyle':'--','color':'orange'}, 
            labels = [''] # 刪除x軸的刻度標(biāo)簽,否則圖形顯示刻度標(biāo)簽為1
           )
# 添加圖形標(biāo)題
plt.title('二手房單價(jià)分布的箱線圖')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第17張圖片
如圖6-17所示,圖中的上下兩條橫線代表上下須、箱體的上下兩條橫線代表上下四分位數(shù)、箱體中的虛線代表中位數(shù)、箱體中的點(diǎn)則為均值、上下須兩端的點(diǎn)代表異常值。通過(guò)圖中均值和中位數(shù)的對(duì)比就可以得知數(shù)據(jù)微微右偏(判斷標(biāo)準(zhǔn):如果數(shù)據(jù)近似正態(tài)分布,則眾數(shù)=中位數(shù)=均值;如果數(shù)據(jù)右偏,則眾數(shù)<中位數(shù)<均值;如果數(shù)值左偏,則眾數(shù)>中位數(shù)>均值)。 如上繪制的是二手房整體單價(jià)的箱線圖,這樣的箱線圖可能并不常見(jiàn),更多的是分組箱線圖,即二手房的單價(jià)按照其他分組變量(如行政區(qū)域、樓層、朝向等)進(jìn)行對(duì)比分析。下面繼續(xù)使用matplotlib模塊對(duì)二手房的單價(jià)繪制分組箱線圖,代碼如下:

            
              # 二手房在各行政區(qū)域的平均單價(jià)
group_region = Sec_Buildings.groupby('region')
avg_price = group_region.aggregate({'price_unit':np.mean}).sort_values('price_unit', ascending = False)

# 通過(guò)循環(huán),將不同行政區(qū)域的二手房存儲(chǔ)到列表中
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軸的刻度標(biāo)簽
            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軸標(biāo)簽
plt.ylabel('單價(jià)(元)')
# 添加標(biāo)題
plt.title('不同行政區(qū)域的二手房單價(jià)對(duì)比')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第18張圖片
應(yīng)用matplotlib模塊繪制如上所示的分組箱線圖會(huì)相對(duì)煩瑣一些,由于boxplot函數(shù)每次只能繪制一個(gè)箱線圖,為了能夠?qū)崿F(xiàn)多個(gè)箱線圖的繪制,對(duì)數(shù)據(jù)稍微做了一些變動(dòng),即將每個(gè)行政區(qū)域下的二手房單價(jià)匯總到一個(gè)列表中,然后基于這個(gè)大列表應(yīng)用boxplot函數(shù)。在繪圖過(guò)程中,首先做了一個(gè)“手腳”,那就是統(tǒng)計(jì)各行政區(qū)域二手房的平均單價(jià),并降序排序,這樣做的目的就是讓分組箱線圖能夠降序呈現(xiàn)。
雖然pandas模塊中的plot方法可以繪制分組箱線圖,但是該方法是基于數(shù)據(jù)框執(zhí)行的,并且數(shù)據(jù)框的每一列對(duì)應(yīng)一個(gè)箱線圖。對(duì)于二手房數(shù)據(jù)集來(lái)說(shuō),應(yīng)用plot方法繪制分組箱線圖不太合適,因?yàn)槊恳粋€(gè)行政區(qū)的二手房數(shù)量不一致,將導(dǎo)致無(wú)法重構(gòu)一個(gè)新的數(shù)據(jù)框用于繪圖。

2.seaborn模塊
如果讀者覺(jué)得matplotlib模塊繪制分組箱線圖比較麻煩,可以使用seaborn模塊中的boxplot函數(shù)。下面不妨先了解一下該函數(shù)的參數(shù)含義:

              
                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軸數(shù)據(jù)。
  • y:指定箱線圖的y軸數(shù)據(jù)。
  • hue:指定分組變量。
  • data:指定用于繪圖的數(shù)據(jù)集。
  • order:傳遞一個(gè)字符串列表,用于分類(lèi)變量的排序。
  • hue_order:傳遞一個(gè)字符串列表,用于分類(lèi)變量hue值的排序。
  • orient:指定箱線圖的呈現(xiàn)方向,默認(rèn)為垂直方向。
  • color:指定所有箱線圖的填充色。
  • palette:指定hue變量的區(qū)分色。
  • saturation:指定顏色的透明度。
  • width:指定箱線圖的寬度。
  • dodge:bool類(lèi)型的參數(shù),當(dāng)使用hue參數(shù)時(shí),是否繪制水平交錯(cuò)的箱線圖,默認(rèn)為T(mén)rue。
  • fliersize:指定異常值點(diǎn)的大小。
  • linewidth:指定箱體邊框的寬度。
  • whis:指定上下須與上下四分位的距離,默認(rèn)為1.5倍的四分位差。
  • notch:bool類(lèi)型的參數(shù),是否繪制凹口箱線圖,默認(rèn)為False。
  • ax:指定子圖的位置。
  • **kwargs:關(guān)鍵字參數(shù),可以調(diào)用plt.boxplot函數(shù)中的其他參數(shù)。

這里仍以上海二手房數(shù)據(jù)為例,應(yīng)用seaborn模塊中的boxplot函數(shù)繪制分組箱線圖,詳細(xì)代碼如下:

            
              # 繪制分組箱線圖
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軸標(biāo)簽
plt.xlabel('')
plt.ylabel('單價(jià)(元)')
# 添加標(biāo)題
plt.title('不同行政區(qū)域的二手房單價(jià)對(duì)比')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第19張圖片
通過(guò)如上代碼,同樣可以得到完全一致的分組箱線圖。這里建議讀者不要直接學(xué)習(xí)和使用pandas模塊和seaborn模塊繪制統(tǒng)計(jì)圖形,而是先把matplotlib模塊摸透,因?yàn)镻ython的核心繪圖模塊是matplotlib。

6.2.3 小提琴圖
小提琴圖是比較有意思的統(tǒng)計(jì)圖形,它將數(shù)值型數(shù)據(jù)的核密度圖與箱線圖融合在一起,進(jìn)而得到一個(gè)形似小提琴的圖形。盡管matplotlib模塊也提供了繪制小提琴圖的函數(shù)violinplot,但是繪制出來(lái)的圖形中并不包含一個(gè)完整的箱線圖,所以本節(jié)將直接使用seaborn模塊中的violinplot函數(shù)繪制小提琴圖。首先,帶領(lǐng)讀者了解一下有關(guān)violinplot函數(shù)的語(yǔ)法和參數(shù)含義:

              
                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軸數(shù)據(jù)。
  • y:指定小提琴圖的y軸數(shù)據(jù)。
  • hue:指定一個(gè)分組變量。
  • data:指定繪制小提琴圖的數(shù)據(jù)集。
  • order:傳遞一個(gè)字符串列表,用于分類(lèi)變量的排序。
  • hue_order:傳遞一個(gè)字符串列表,用于分類(lèi)變量hue值的排序。
  • bw:指定核密度估計(jì)的帶寬,帶寬越大,密度曲線越光滑。
  • scale:用于調(diào)整小提琴圖左右的寬度,如果為area,則表示每個(gè)小提琴圖左右部分擁有相同的面積;如果為count,則表示根據(jù)樣本數(shù)量來(lái)調(diào)節(jié)寬度;如果為width,則表示每個(gè)小提琴圖左右兩部分擁有相同的寬度。
  • scale_hue:bool類(lèi)型參數(shù),當(dāng)使用hue參數(shù)時(shí),是否對(duì)hue變量的每個(gè)水平做標(biāo)準(zhǔn)化處理,默認(rèn)為T(mén)rue。
  • width:使用hue參數(shù)時(shí),用于控制小提琴圖的寬度。
  • inner:指定小提琴圖內(nèi)部數(shù)據(jù)點(diǎn)的形態(tài),如果為box,則表示繪制微型的箱線圖;如果為quartiles,則表示繪制四分位的分布圖;如果為point或stick,則表示繪制點(diǎn)或小豎條。
  • split:bool類(lèi)型參數(shù),使用hue參數(shù)時(shí),將小提琴圖從中間分為兩個(gè)不同的部分,默認(rèn)為False。
  • dodge:bool類(lèi)型的參數(shù),當(dāng)使用hue參數(shù)時(shí),是否繪制水平交錯(cuò)的小提琴圖,默認(rèn)為T(mén)rue。
  • orient:指定小提琴圖的呈現(xiàn)方向,默認(rèn)為垂直方向。
  • linewidth:指定小提琴圖的所有線條寬度。
  • color:指定小提琴圖的顏色,該參數(shù)與palette參數(shù)一起使用時(shí)無(wú)效。
  • palette:指定hue變量的區(qū)分色。
  • saturation:指定顏色的透明度。
  • ax:指定子圖的位置。

接下來(lái),以酒吧的消費(fèi)數(shù)據(jù)為例(數(shù)據(jù)包含客戶的消費(fèi)金額、消費(fèi)時(shí)間、打賞金額、客戶性別、是否抽煙等字段),利用如上介紹的函數(shù)繪制分組小提琴圖,以幫助讀者進(jìn)一步了解參數(shù)的含義,繪圖代碼如下:

            
              # 讀取數(shù)據(jù)
tips = pd.read_csv(r'D:\PyProject\data\tips.csv')
# 繪制分組小提琴圖
sns.violinplot(x = "total_bill", # 指定x軸的數(shù)據(jù)
               y = "day", # 指定y軸的數(shù)據(jù)
               hue = "sex", # 指定分組變量
               data = tips, # 指定繪圖的數(shù)據(jù)集
               order = ['Thur','Fri','Sat','Sun'], # 指定x軸刻度標(biāo)簽的順序
               scale = 'count', # 以男女客戶數(shù)調(diào)節(jié)小提琴圖左右的寬度
               split = True, # 將小提琴圖從中間割裂開(kāi),形成不同的密度曲線;
               palette = 'RdBu' # 指定不同性別對(duì)應(yīng)的顏色(因?yàn)閔ue參數(shù)為設(shè)置為性別變量)
              )
# 添加圖形標(biāo)題
plt.title('每天不同性別客戶的消費(fèi)額情況')
# 設(shè)置圖例
plt.legend(loc = 'upper center', ncol = 2)
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第20張圖片
如圖6-19所示,得到了分組的小提琴圖,讀者會(huì)發(fā)現(xiàn),小提琴圖的左右兩邊并不對(duì)稱(chēng),是因?yàn)橥瑫r(shí)使用了hue參數(shù)和split參數(shù),兩邊的核密度圖代表了不同性別客戶的消費(fèi)額分布。從這張圖中,一共可以反映四個(gè)維度的信息,y軸表示客戶的消費(fèi)額、x軸表示客戶的消費(fèi)時(shí)間、顏色圖例表示客戶的性別、左右核密度圖的寬度代表了樣本量。以周五和周六兩天為例,周五的男女客戶數(shù)量差異不大,而周六男性客戶要比女性客戶多得多,那是因?yàn)橛野脒叺暮嗣芏葓D更寬一些。

6.2.4 折線圖
對(duì)于時(shí)間序列數(shù)據(jù)而言,一般都會(huì)使用折線圖反映數(shù)據(jù)背后的趨勢(shì)。通常折線圖的橫坐標(biāo)指代日期數(shù)據(jù),縱坐標(biāo)代表某個(gè)數(shù)值型變量,當(dāng)然還可以使用第三個(gè)離散變量對(duì)折線圖進(jìn)行分組處理。接下來(lái)僅使用Python中的matplotlib模塊和pandas模塊實(shí)現(xiàn)折線圖的繪制。盡管seaborn模塊中的tsplot函數(shù)也可以繪制時(shí)間序列的折線圖,但是該函數(shù)非常不合理,故不在本節(jié)中介紹。

1.matplotlib模塊
折線圖的繪制可以使用matplotlib模塊中的plot函數(shù)實(shí)現(xiàn)。關(guān)于該函數(shù)的語(yǔ)法和參數(shù)含義如下:

              
                plt.plot(x, y, linestyle, linewidth, color, marker,
     markersize, markeredgecolor, markerfactcolor,
     markeredgewidth, label, alpha)

              
            
  • x:指定折線圖的x軸數(shù)據(jù)。
  • y:指定折線圖的y軸數(shù)據(jù)。
  • linestyle:指定折線的類(lèi)型,可以是實(shí)線、虛線、點(diǎn)虛線、點(diǎn)點(diǎn)線等,默認(rèn)為實(shí)線。
  • linewidth:指定折線的寬度。
  • marker:可以為折線圖添加點(diǎn),該參數(shù)是設(shè)置點(diǎn)的形狀。
  • markersize:設(shè)置點(diǎn)的大小。
  • markeredgecolor:設(shè)置點(diǎn)的邊框色。
  • markerfactcolor:設(shè)置點(diǎn)的填充色。
  • markeredgewidth:設(shè)置點(diǎn)的邊框?qū)挾取?
  • label:為折線圖添加標(biāo)簽,類(lèi)似于圖例的作用。

為了進(jìn)一步理解plot函數(shù)中的參數(shù)含義,這里以某微信公眾號(hào)的閱讀人數(shù)和閱讀人次為例(數(shù)據(jù)包含日期、人數(shù)和人次三個(gè)字段),繪制2017年第四季度微信文章閱讀人數(shù)的折線圖,代碼如下:

            
              # 數(shù)據(jù)讀取
wechat = pd.read_excel(r'D:\PyProject\data\wechat.xlsx')
# 繪制單條折線圖
plt.plot(wechat.Date, # x軸數(shù)據(jù)
         wechat.Counts, # y軸數(shù)據(jù)
         linestyle = '-', # 折線類(lèi)型
         linewidth = 2, # 折線寬度
         color = 'steelblue', # 折線顏色
         marker = 'o', # 折線圖中添加圓點(diǎn)
         markersize = 6, # 點(diǎn)的大小
         markeredgecolor='black', # 點(diǎn)的邊框色
         markerfacecolor='brown') # 點(diǎn)的填充色
# 添加y軸標(biāo)簽
plt.ylabel('人數(shù)')
# 添加圖形標(biāo)題
plt.title('每天微信文章閱讀人數(shù)趨勢(shì)')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第21張圖片
如圖6-20所示,在繪制折線圖的同時(shí),也添加了每個(gè)數(shù)據(jù)對(duì)應(yīng)的圓點(diǎn)。讀者可能會(huì)注意到,代碼中折線類(lèi)型和點(diǎn)類(lèi)型分別用一個(gè)減號(hào)-(代表實(shí)線)和字母o(代表空心圓點(diǎn))表示。是否還有其他的表示方法?這里將常用的線型和點(diǎn)型匯總到表6-1和表6-2中。

第六章Python數(shù)據(jù)可視化_第22張圖片
雖然上面的圖形可以反映有關(guān)微信文章閱讀人數(shù)的波動(dòng)趨勢(shì),但是為了進(jìn)一步改進(jìn)這個(gè)折線圖,還需要解決兩個(gè)問(wèn)題:

  • 如何將微信文章的閱讀人數(shù)和閱讀人次同時(shí)呈現(xiàn)在圖中。
  • 對(duì)于x軸的刻度標(biāo)簽,是否可以只保留月份和日期,并且以7天作為間隔。
            
              # 繪制兩條折線圖
# 導(dǎo)入模塊,用于日期刻度的修改
import matplotlib as mpl
# 繪制閱讀人數(shù)折線圖
plt.plot(wechat.Date, # x軸數(shù)據(jù)
         wechat.Counts, # y軸數(shù)據(jù)
         linestyle = '-', # 折線類(lèi)型,實(shí)心線
         color = 'steelblue', # 折線顏色
         label = '閱讀人數(shù)'
         )
# 繪制閱讀人次折線圖
plt.plot(wechat.Date, # x軸數(shù)據(jù)
         wechat.Times, # y軸數(shù)據(jù)
         linestyle = '--', # 折線類(lèi)型,虛線
         color = 'indianred', # 折線顏色
         label = '閱讀人次'
         )

# 獲取圖的坐標(biāo)信息
ax = plt.gca()
# 設(shè)置日期的顯示格式  
date_format = mpl.dates.DateFormatter("%m-%d")  
ax.xaxis.set_major_formatter(date_format) 
# 設(shè)置x軸顯示多少個(gè)日期刻度
# xlocator = mpl.ticker.LinearLocator(10)
# 設(shè)置x軸每個(gè)刻度的間隔天數(shù)
xlocator = mpl.ticker.MultipleLocator(7)
ax.xaxis.set_major_locator(xlocator)
# 為了避免x軸刻度標(biāo)簽的緊湊,將刻度標(biāo)簽旋轉(zhuǎn)45度
plt.xticks(rotation=45)

# 添加y軸標(biāo)簽
plt.ylabel('人數(shù)')
# 添加圖形標(biāo)題
plt.title('每天微信文章閱讀人數(shù)與人次趨勢(shì)')
# 添加圖例
plt.legend()
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第23張圖片
如圖6-21所示,恰到好處地解決了之前提出的兩個(gè)問(wèn)題。上面的繪圖代碼可以分解為兩個(gè)核心部分:

  • 運(yùn)用兩次plot函數(shù)分別繪制閱讀人數(shù)和閱讀人次的折線圖,最終通過(guò)plt.show()將兩條折線呈現(xiàn)在一張圖中。
  • 日期型軸刻度的設(shè)置,ax變量用來(lái)獲取原始狀態(tài)的軸屬性,然后基于ax對(duì)象修改刻度的顯示方式,一個(gè)是僅包含月日的格式,另一個(gè)是每7天作為一個(gè)間隔。

2.pandas模塊
如果使用pandas模塊繪制折線圖,調(diào)用的仍然是plot方法,接下來(lái)以2015—2017年上海每天的最高氣溫?cái)?shù)據(jù)為例,繪制每月平均最高氣溫的三條折線圖,具體代碼如下:

            
              # 讀取天氣數(shù)據(jù)
weather = pd.read_excel(r'D:\PyProject\data\weather.xlsx')
# 統(tǒng)計(jì)每月的平均最高氣溫
data = weather.pivot_table(index = 'month', columns='year', values='high')
# 繪制折線圖
data.plot(kind = 'line', 
          style = ['-','--',':'] # 設(shè)置折線圖的線條類(lèi)型
         )
# 修改x軸和y軸標(biāo)簽
plt.xlabel('月份')
plt.ylabel('氣溫')
# 添加圖形標(biāo)題
plt.title('每月平均最高氣溫波動(dòng)趨勢(shì)')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第24張圖片

如圖6-22所示,圖中表示的是各年份中每月平均最高氣溫的走勢(shì),雖然繪圖的核心部分(plot過(guò)程)很簡(jiǎn)單,但是前提需要將原始數(shù)據(jù)集轉(zhuǎn)換成可以繪制多條折線圖的格式,即構(gòu)成三條折線圖的數(shù)據(jù)分別為數(shù)據(jù)框的三個(gè)字段。為了構(gòu)造特定需求的數(shù)據(jù)集,使用了數(shù)據(jù)框的pivot_table方法,形成一張滿足條件的透視表。圖6-23所示就是數(shù)據(jù)集轉(zhuǎn)換的前后對(duì)比。

第六章Python數(shù)據(jù)可視化_第25張圖片

6.3 關(guān)系型數(shù)據(jù)的可視化

前面的兩節(jié)內(nèi)容都是基于獨(dú)立的離散變量或數(shù)值變量進(jìn)行的可視化展現(xiàn)。在眾多的可視化圖形中,有一類(lèi)圖形專(zhuān)門(mén)用于探究?jī)蓚€(gè)或三個(gè)變量之間的關(guān)系。例如,散點(diǎn)圖用于發(fā)現(xiàn)兩個(gè)數(shù)值變量之間的關(guān)系,氣泡圖可以展現(xiàn)三個(gè)數(shù)值變量之間的關(guān)系,熱力圖則體現(xiàn)了兩個(gè)離散變量之間的組合關(guān)系。
本節(jié)將使用matplotlib模塊、pandas模塊和seaborn模塊繪制上述所介紹的三種關(guān)系型圖形。下面首先了解一下最常用的散點(diǎn)圖是如何繪制的。

6.3.1 散點(diǎn)圖
如果需要研究?jī)蓚€(gè)數(shù)值型變量之間是否存在某種關(guān)系,例如正向的線性關(guān)系,或者是趨勢(shì)性的非線性關(guān)系,那么散點(diǎn)圖將是最佳的選擇。

1.matplotlib模塊
matplotlib模塊中的scatter函數(shù)可以非常方便地繪制兩個(gè)數(shù)值型變量的散點(diǎn)圖。這里首先將該函數(shù)的語(yǔ)法及參數(shù)含義寫(xiě)在下方,以便讀者掌握函數(shù)的使用:

              
                scatter(x, y, s=20, c=None, marker='o', cmap=None, norm=None, vmin=None,
     vmax=None, alpha=None, linewidths=None, edgecolors=None)

              
            

x:指定散點(diǎn)圖的x軸數(shù)據(jù)。 y:指定散點(diǎn)圖的y軸數(shù)據(jù)。 s:指定散點(diǎn)圖點(diǎn)的大小,默認(rèn)為20,通過(guò)傳入其他數(shù)值型變量,可以實(shí)現(xiàn)氣泡圖的繪制。 c:指定散點(diǎn)圖點(diǎn)的顏色,默認(rèn)為藍(lán)色,也可以傳遞其他數(shù)值型變量,通過(guò)cmap參數(shù)的色階表示數(shù)值大小。 marker:指定散點(diǎn)圖點(diǎn)的形狀,默認(rèn)為空心圓。 cmap:指定某個(gè)Colormap值,只有當(dāng)c參數(shù)是一個(gè)浮點(diǎn)型數(shù)組時(shí)才有效。 norm:設(shè)置數(shù)據(jù)亮度,標(biāo)準(zhǔn)化到0~1,使用該參數(shù)仍需要參數(shù)c為浮點(diǎn)型的數(shù)組。 vmin、vmax:亮度設(shè)置,與norm類(lèi)似,如果使用norm參數(shù),則該參數(shù)無(wú)效。 alpha:設(shè)置散點(diǎn)的透明度。 linewidths:設(shè)置散點(diǎn)邊界線的寬度。 edgecolors:設(shè)置散點(diǎn)邊界線的顏色。

下面以iris數(shù)據(jù)集為例,探究如何應(yīng)用matplotlib模塊中的scatter函數(shù)繪制花瓣寬度與長(zhǎng)度之間的散點(diǎn)圖,繪圖代碼如下:

            
              # 讀入數(shù)據(jù)
iris = pd.read_csv(r'D:\PyProject\data\iris.csv')
# 繪制散點(diǎn)圖
plt.scatter(x = iris.Petal_Width, # 指定散點(diǎn)圖的x軸數(shù)據(jù)
            y = iris.Petal_Length, # 指定散點(diǎn)圖的y軸數(shù)據(jù)
            color = 'steelblue' # 指定散點(diǎn)圖中點(diǎn)的顏色
           )
# 添加x軸和y軸標(biāo)簽
plt.xlabel('花瓣寬度')
plt.ylabel('花瓣長(zhǎng)度')
# 添加標(biāo)題
plt.title('鳶尾花的花瓣寬度與長(zhǎng)度關(guān)系')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第26張圖片
如圖6-24所示,通過(guò)scatter函數(shù)就可以非常簡(jiǎn)單地繪制出花瓣寬度與長(zhǎng)度的散點(diǎn)圖。如果使用pandas模塊中的plot方法,同樣可以很簡(jiǎn)單地繪制出散點(diǎn)圖。

2.pandas模塊

            
              # Pandas模塊繪制散點(diǎn)圖
# 繪制散點(diǎn)圖
iris.plot(x = 'Petal_Width', y = 'Petal_Length', kind = 'scatter', title = '鳶尾花的花瓣寬度與長(zhǎng)度關(guān)系')
# 修改x軸和y軸標(biāo)簽
plt.xlabel('花瓣寬度')
plt.ylabel('花瓣長(zhǎng)度')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第27張圖片
盡管使用這兩個(gè)模塊都可以非常方便地繪制出散點(diǎn)圖,但是繪制分組散點(diǎn)圖會(huì)稍微復(fù)雜一點(diǎn)。如果讀者使用seaborn模塊中的lmplot函數(shù),那么繪制分組散點(diǎn)圖就太簡(jiǎn)單了,而且該函數(shù)還可以根據(jù)散點(diǎn)圖添加線性擬合線。

3.seaborn模塊
為了使讀者清楚地掌握l(shuí)mplot函數(shù)的使用方法,有必要介紹一下該函數(shù)的語(yǔ)法和參數(shù)含義:

              
                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軸的數(shù)據(jù)。
  • data:指定繪圖的數(shù)據(jù)集。
  • hue:指定分組變量。
  • col,row:用于繪制分面圖形,指定分面圖形的列向與行向變量。
  • palette:為hue參數(shù)指定的分組變量設(shè)置顏色。
  • col_wrap:設(shè)置分面圖形中每行子圖的數(shù)量。
  • size:用于設(shè)置每個(gè)分面圖形的高度。
  • aspect:用于設(shè)置每個(gè)分面圖形的寬度,寬度等于size*aspect。
  • markers:設(shè)置點(diǎn)的形狀,用于區(qū)分hue參數(shù)指定的變量水平值。
  • sharex,sharey:bool類(lèi)型參數(shù),設(shè)置繪制分面圖形時(shí)是否共享x軸和y軸,默認(rèn)為T(mén)rue。 hue_order,col_order,row_order:為hue參數(shù)、col參數(shù)和row參數(shù)指定的分組變量設(shè)值水平值順序。
  • legend:bool類(lèi)型參數(shù),是否顯示圖例,默認(rèn)為T(mén)rue。
  • legend_out:bool類(lèi)型參數(shù),是否將圖例放置在圖框外,默認(rèn)為T(mén)rue。
  • scatter:bool類(lèi)型參數(shù),是否繪制散點(diǎn)圖,默認(rèn)為T(mén)rue。 fit_reg:bool類(lèi)型參數(shù),是否擬合線性回歸,默認(rèn)為T(mén)rue。
  • ci:繪制擬合線的置信區(qū)間,默認(rèn)為95%的置信區(qū)間。
  • n_boot:為了估計(jì)置信區(qū)間,指定自助重抽樣的次數(shù),默認(rèn)為1000次。 order:指定多項(xiàng)式回歸,默認(rèn)指數(shù)為1。
  • logistic:bool類(lèi)型參數(shù),是否擬合邏輯回歸,默認(rèn)為False。 lowess:bool類(lèi)型參數(shù),是否擬合局部多項(xiàng)式回歸,默認(rèn)為False。
  • robust:bool類(lèi)型參數(shù),是否擬合魯棒回歸,默認(rèn)為False。
  • logx:bool類(lèi)型參數(shù),是否對(duì)x軸做對(duì)數(shù)變換,默認(rèn)為False。
  • x_partial,y_partial:為x軸數(shù)據(jù)和y軸數(shù)據(jù)指定控制變量,即排除x_partial和y_partial變量的影響下繪制散點(diǎn)圖。
  • truncate:bool類(lèi)型參數(shù),是否根據(jù)實(shí)際數(shù)據(jù)的范圍對(duì)擬合線做截?cái)嗖僮?,默認(rèn)為False。
  • x_jitter,y_jitter:為x軸變量或y軸變量添加隨機(jī)噪聲,當(dāng)x軸數(shù)據(jù)與y軸數(shù)據(jù)比較密集時(shí),可以使用這兩個(gè)參數(shù)。
  • scatter_kws:設(shè)置點(diǎn)的其他屬性,如點(diǎn)的填充色、邊框色、大小等。
  • line_kws:設(shè)置擬合線的其他屬性,如線的形狀、顏色、粗細(xì)等。

該函數(shù)的參數(shù)雖然比較多,但是大多數(shù)情況下讀者只需使用幾個(gè)重要的參數(shù),如x、y、hue、data等。接下來(lái)仍以iris數(shù)據(jù)集為例,繪制分組散點(diǎn)圖,繪圖代碼如下:

            
              # seaborn模塊繪制分組散點(diǎn)圖
sns.lmplot(x = 'Petal_Width', # 指定x軸變量
           y = 'Petal_Length', # 指定y軸變量
           hue = 'Species', # 指定分組變量
           data = iris, # 指定繪圖數(shù)據(jù)集
           legend_out = False, # 將圖例呈現(xiàn)在圖框內(nèi)
           truncate=True # 根據(jù)實(shí)際的數(shù)據(jù)范圍,對(duì)擬合線作截?cái)嗖僮?          )
# 修改x軸和y軸標(biāo)簽
plt.xlabel('花瓣寬度')
plt.ylabel('花瓣長(zhǎng)度')
# 添加標(biāo)題
plt.title('鳶尾花的花瓣寬度與長(zhǎng)度關(guān)系')
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第28張圖片
如圖6-25所示,lmplot函數(shù)不僅可以繪制分組散點(diǎn)圖,還可以對(duì)每個(gè)組內(nèi)的散點(diǎn)添加回歸線(圖6-25默認(rèn)擬合線性回歸線)。分組效果的體現(xiàn)是通過(guò)hue參數(shù)設(shè)置的,如果需要擬合其他回歸線,可以指定lowess參數(shù)(局部多項(xiàng)式回歸)、logistic參數(shù)(邏輯回歸)、order參數(shù)(多項(xiàng)式回歸)和robust參數(shù)(魯棒回歸)。

6.3.2 氣泡圖
上一節(jié)所介紹的散點(diǎn)圖都是反映兩個(gè)數(shù)值型變量的關(guān)系,如果還想通過(guò)散點(diǎn)圖添加第三個(gè)數(shù)值型變量的信息,一般可以使用氣泡圖。氣泡圖的實(shí)質(zhì)就是通過(guò)第三個(gè)數(shù)值型變量控制每個(gè)散點(diǎn)的大小,點(diǎn)越大,代表的第三維數(shù)值越高,反之亦然。接下來(lái)將會(huì)介紹如何通過(guò)Python繪制氣泡圖。
在上一節(jié)中,應(yīng)用matplotlib模塊中的scatter函數(shù)繪制了散點(diǎn)圖,本節(jié)將繼續(xù)使用該函數(shù)繪制氣泡圖。要實(shí)現(xiàn)氣泡圖的繪制,關(guān)鍵的參數(shù)是s,即散點(diǎn)圖中點(diǎn)的大小,如果將數(shù)值型變量傳遞給該參數(shù),就可以輕松繪制氣泡圖了。如果讀者對(duì)該函數(shù)的參數(shù)含義還不是很了解,可以查看上一節(jié)中的參數(shù)含義說(shuō)明。
下面以某超市的商品類(lèi)別銷(xiāo)售數(shù)據(jù)為例,繪制銷(xiāo)售額、利潤(rùn)和利潤(rùn)率之間的氣泡圖,探究三者之間的關(guān)系,繪圖代碼如下:

            
              # 讀取數(shù)據(jù)
Prod_Category = pd.read_excel(r'D:\PyProject\data\SuperMarket.xlsx')
# 將利潤(rùn)率標(biāo)準(zhǔn)化到[0,1]之間(因?yàn)槔麧?rùn)率中有負(fù)數(shù)),然后加上微小的數(shù)值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
            )
# 繪制技術(shù)產(chǎn)品的氣泡圖
plt.scatter(x = Prod_Category.Sales[Prod_Category.Category == '技術(shù)產(chǎn)品'], 
           y = Prod_Category.Profit[Prod_Category.Category == '技術(shù)產(chǎn)品'], 
           s = Prod_Category.std_ratio[Prod_Category.Category == '技術(shù)產(chǎn)品']*1000,
           color = 'indianred' , label = '技術(shù)產(chǎn)品', alpha = 0.6
          )
# 繪制家具產(chǎn)品的氣泡圖
plt.scatter(x = Prod_Category.Sales[Prod_Category.Category == '家具產(chǎn)品'], 
           y = Prod_Category.Profit[Prod_Category.Category == '家具產(chǎn)品'], 
           s = Prod_Category.std_ratio[Prod_Category.Category == '家具產(chǎn)品']*1000,
           color = 'black' , label = '家具產(chǎn)品', alpha = 0.6
          )
# 添加x軸和y軸標(biāo)簽
plt.xlabel('銷(xiāo)售額')
plt.ylabel('利潤(rùn)')
# 添加標(biāo)題
plt.title('銷(xiāo)售額、利潤(rùn)及利潤(rùn)率的氣泡圖')
# 添加圖例
plt.legend()
# 顯示圖形
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第29張圖片
如圖6-26所示,應(yīng)用scatter函數(shù)繪制了分組氣泡圖,從圖中可知,辦公用品和家具產(chǎn)品的利潤(rùn)率波動(dòng)比較大(因?yàn)檫@兩類(lèi)圓點(diǎn)大小不均)。從代碼角度來(lái)看,繪圖的核心部分是使用三次scatter函數(shù),而且代碼結(jié)構(gòu)完全一樣,如果讀者對(duì)for循環(huán)掌握得比較好,完全可以使用循環(huán)的方式替換三次scatter函數(shù)的重復(fù)應(yīng)用。
需要說(shuō)明的是,如果s參數(shù)對(duì)應(yīng)的變量值小于等于0,則對(duì)應(yīng)的氣泡點(diǎn)是無(wú)法繪制出來(lái)的。這里提供一個(gè)解決思路,就是先將該變量標(biāo)準(zhǔn)化為[0,1],再加上一個(gè)非常小的值,如0.001。如上代碼所示,最后對(duì)s參數(shù)擴(kuò)大500倍的目的就是凸顯氣泡的大小。
遺憾的是,pandas模塊和seaborn模塊中沒(méi)有繪制氣泡圖的方法或函數(shù),故這里就不再衍生了。如果讀者確實(shí)需要繪制氣泡圖,又覺(jué)得matplotlib模塊中的scatter函數(shù)用起來(lái)比較燦瑣,可以使用Python的bokeh模塊,有關(guān)該模塊的詳細(xì)內(nèi)容,可以查看官方文檔。

6.3.3 熱力圖

最后介紹另一種關(guān)系型數(shù)據(jù)的可視化圖形,即熱力圖,有時(shí)也稱(chēng)之為交叉填充表。該圖形最典型的用法就是實(shí)現(xiàn)列聯(lián)表的可視化,即通過(guò)圖形的方式展現(xiàn)兩個(gè)離散變量之間的組合關(guān)系。讀者可以借助于seaborn模塊中的heatmap函數(shù),完成熱力圖的繪制。按照慣例,首先對(duì)該函數(shù)的用法及參數(shù)含義做如下解釋?zhuān)?

              
                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:指定繪制熱力圖的數(shù)據(jù)集。
  • vmin,vmax:用于指定圖例中最小值與最大值的顯示值。
  • cmap:指定一個(gè)colormap對(duì)象,用于熱力圖的填充色。
  • center:指定顏色中心值,通過(guò)該參數(shù)可以調(diào)整熱力圖的顏色深淺。
  • annot:指定一個(gè)bool類(lèi)型的值或與data參數(shù)形狀一樣的數(shù)組,如果為T(mén)rue,就在熱力圖的每個(gè)單元上顯示數(shù)值。
  • fmt:指定單元格中數(shù)據(jù)的顯示格式。
  • annot_kws:有關(guān)單元格中數(shù)值標(biāo)簽的其他屬性描述,如顏色、大小等。
  • linewidths:指定每個(gè)單元格的邊框?qū)挾取?
  • linecolor:指定每個(gè)單元格的邊框顏色。
  • cbar:bool類(lèi)型參數(shù),是否用顏色條作為圖例,默認(rèn)為T(mén)rue。
  • square:bool類(lèi)型參數(shù),是否使熱力圖的每個(gè)單元格為正方形,默認(rèn)為False。
  • cbar_kws:有關(guān)顏色條的其他屬性描述。
  • xticklabels,yticklabels:指定熱力圖x軸和y軸的刻度標(biāo)簽,如果為T(mén)rue,則分別以數(shù)據(jù)框的變量名和行名稱(chēng)作為刻度標(biāo)簽。
  • mask:用于突出顯示某些數(shù)據(jù)。
  • ax:用于指定子圖的位置。

接下來(lái),以某服裝店的交易數(shù)據(jù)為例,統(tǒng)計(jì)2009—2012年每個(gè)月的銷(xiāo)售總額,然后運(yùn)用如上介紹的heatmap函數(shù)對(duì)統(tǒng)計(jì)結(jié)果進(jìn)行可視化展現(xiàn),具體代碼如下:

            
              # 讀取數(shù)據(jù)
Sales = pd.read_excel(r'D:\PyProject\data\Sales.xlsx')
# 根據(jù)交易日期,衍生出年份和月份字段
Sales['year'] = Sales.Date.dt.year
Sales['month'] = Sales.Date.dt.month
# 統(tǒng)計(jì)每年各月份的銷(xiāo)售總額
Summary = Sales.pivot_table(index = 'month', columns = 'year', values = 'Sales', aggfunc = np.sum)

# 繪制熱力圖
sns.heatmap(data = Summary, # 指定繪圖數(shù)據(jù)
            cmap = 'PuBuGn', # 指定填充色
            linewidths = .1, # 設(shè)置每個(gè)單元格邊框的寬度
            annot = True, # 顯示數(shù)值
            fmt = '.1e' # 以科學(xué)計(jì)算法顯示數(shù)據(jù)
            )
#添加標(biāo)題
plt.title('每年各月份銷(xiāo)售總額熱力圖')
# 顯示圖形
plt.show()

            
          

第六章Python數(shù)據(jù)可視化_第30張圖片
如表6-3所示,它是列聯(lián)表的格式,反映的是每年各月份的銷(xiāo)售總額。很顯然,通過(guò)肉眼是無(wú)法迅速發(fā)現(xiàn)銷(xiāo)售業(yè)績(jī)?cè)诟髟路葜械牟町惖?,如果將?shù)據(jù)表以熱力圖的形式展現(xiàn),問(wèn)題就會(huì)簡(jiǎn)單很多。
第六章Python數(shù)據(jù)可視化_第31張圖片
如圖6-27所示就是將表格進(jìn)行可視化的結(jié)果,每個(gè)單元格顏色的深淺代表數(shù)值的高低,通過(guò)顏色就能迅速發(fā)現(xiàn)每年各月份銷(xiāo)售情況的好壞。

6.4 多個(gè)圖形的合并

工作中往往會(huì)根據(jù)業(yè)務(wù)需求,將繪制的多個(gè)圖形組合到一個(gè)大圖框內(nèi),形成類(lèi)似儀表板的效果。針對(duì)這種情況,如何應(yīng)用Python將前面所學(xué)的各種圖形匯總到一個(gè)圖表中,這將是本節(jié)所要學(xué)習(xí)的重點(diǎn)。
關(guān)于多種圖形的組合,可以使用matplotlib模塊中的subplot2grid函數(shù)。這個(gè)函數(shù)的靈活性非常高,構(gòu)成的組合圖既可以是m×n的矩陣風(fēng)格,也可以是跨行或跨列的矩陣風(fēng)格。接下來(lái),對(duì)該函數(shù)的用法和參數(shù)含義加以說(shuō)明:

              
                subplot2grid(shape, loc, rowspan=1, colspan=1, **kwargs)

              
            
  • shape:指定組合圖的框架形狀,以元組形式傳遞,如2×3的矩陣可以表示成(2,3)。
  • loc:指定子圖所在的位置,如shape中第一行第一列可以表示成(0,0)。
  • rowspan:指定某個(gè)子圖需要跨幾行。
  • colspan:指定某個(gè)子圖需要跨幾列。

為了使讀者理解函數(shù)中的四個(gè)參數(shù),這里以2×3的組圖布局為例,說(shuō)明子圖位置與跨行、跨列的概念,如圖6-28所示。
第六章Python數(shù)據(jù)可視化_第32張圖片
這兩種布局的前提都需要設(shè)置shape參數(shù)為(2,3),所不同的是,左圖一共需要布置6個(gè)圖形;右圖只需要布置4個(gè)圖形,其中第三列跨了兩行(rowspan需要指定為2),第二行跨了兩列(colspan需要指定為2)。圖框中的元組值代表了子圖的位置。接下來(lái)以某集市商品交易數(shù)據(jù)為例,繪制含跨行和跨列的組合圖,代碼如下:

            
              # 讀取數(shù)據(jù)
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

# 設(shè)置大圖框的長(zhǎng)和高
plt.figure(figsize = (12,6))
# 設(shè)置第一個(gè)子圖的布局
ax1 = plt.subplot2grid(shape = (2,3), loc = (0,0))
# 統(tǒng)計(jì)2012年各訂單等級(jí)的數(shù)量
Class_Counts = Prod_Trade.Order_Class[Prod_Trade.year == 2012].value_counts()
Class_Percent = Class_Counts/Class_Counts.sum()
# 將餅圖設(shè)置為圓形(否則有點(diǎn)像橢圓)
ax1.set_aspect(aspect = 'equal')
# 繪制訂單等級(jí)餅圖
ax1.pie(x = Class_Percent.values, labels = Class_Percent.index, autopct = '%.1f%%')
# 添加標(biāo)題
ax1.set_title('各等級(jí)訂單比例')

# 設(shè)置第二個(gè)子圖的布局
ax2 = plt.subplot2grid(shape = (2,3), loc = (0,1))
# 統(tǒng)計(jì)2012年每月銷(xiāo)售額
Month_Sales = Prod_Trade[Prod_Trade.year == 2012].groupby(by = 'month').aggregate({'Sales':np.sum})
# 繪制銷(xiāo)售額趨勢(shì)圖
Month_Sales.plot(title = '2012年各月銷(xiāo)售趨勢(shì)', ax = ax2, legend = False)
# 刪除x軸標(biāo)簽
ax2.set_xlabel('')

# 設(shè)置第三個(gè)子圖的布局
ax3 = plt.subplot2grid(shape = (2,3), loc = (0,2), rowspan = 2)
# 繪制各運(yùn)輸方式的成本箱線圖
sns.boxplot(x = 'Transport', y = 'Trans_Cost', data = Prod_Trade, ax = ax3)
# 添加標(biāo)題
ax3.set_title('各運(yùn)輸方式成本分布')
# 刪除x軸標(biāo)簽
ax3.set_xlabel('')
# 修改y軸標(biāo)簽
ax3.set_ylabel('運(yùn)輸成本')

# 設(shè)置第四個(gè)子圖的布局
ax4 = plt.subplot2grid(shape = (2,3), loc = (1,0), colspan = 2)
# 2012年客單價(jià)分布直方圖
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'}))
# 添加標(biāo)題
ax4.set_title('2012年客單價(jià)分布圖')
# 修改x軸標(biāo)簽
ax4.set_xlabel('銷(xiāo)售額')

# 調(diào)整子圖之間的水平間距和高度間距
plt.subplots_adjust(hspace=0.6, wspace=0.3)
# 圖形顯示
plt.show()

            
          

結(jié)果:
第六章Python數(shù)據(jù)可視化_第33張圖片
如圖6-29所示,構(gòu)成了2×3風(fēng)格的組合圖,其中兩幅子圖是跨行和跨列的,而且這里特地選了matplotlib模塊、pandas模塊和seabron模塊繪制子圖,目的是讓讀者能夠掌握不同模塊圖形的組合。針對(duì)如上代碼,需要講解幾個(gè)重要的知識(shí)點(diǎn):

  • 在繪制每一幅子圖之前,都需要運(yùn)用subplot2grid函數(shù)控制子圖的位置,并傳遞給一個(gè)變量對(duì)象(如代碼中的ax1、ax2等)。
  • 為了使子圖位置(ax1、ax2等)產(chǎn)生效果,不同的繪圖模塊需要應(yīng)用不同的方法。如果通過(guò)matplotlib模塊繪制子圖,則必須使用ax1.plot_function的代碼語(yǔ)法(如上代碼中,繪制餅圖的過(guò)程);如果通過(guò)pandas模塊或seaborn模塊繪制子圖,則需要為繪圖“方法”或函數(shù)指定ax參數(shù)(如上代碼中,繪制折線圖、直方圖和箱線圖的過(guò)程)。
  • 如果為子圖添加標(biāo)題、坐標(biāo)軸標(biāo)簽、刻度值標(biāo)簽等,不能直接使用plt.title、plt.xlabel、plt.xticks等函數(shù),而是換成ax1.set_*的形式(可參考如上代碼中對(duì)子圖標(biāo)題、坐標(biāo)軸標(biāo)簽的設(shè)置)。
  • 由于子圖之間的默認(rèn)寬間距和高間距不太合理,故需要通過(guò)subplots_adjust函數(shù)重新修改子圖之間的水平間距和垂直間距(如倒數(shù)第二行代碼所示)。

6.5 本章小結(jié)

本章的主題是關(guān)于數(shù)據(jù)的可視化,通過(guò)每一個(gè)具體的案例介紹了有關(guān)matplotlib模塊、pandas模塊和seaborn模塊的繪圖函數(shù)和參數(shù)含義,分別針對(duì)離散型數(shù)據(jù)、數(shù)值型數(shù)據(jù)和關(guān)系型數(shù)據(jù)講解了最為常用的可視化圖形,包括餅圖、條形圖、直方圖、核密度曲線、箱線圖、小提琴圖、折線圖、散點(diǎn)圖、氣泡圖和熱力圖。最后,借助于subplot2grid函數(shù)實(shí)現(xiàn)各種模塊下圖形的組合。
通過(guò)Python完成數(shù)據(jù)可視化的模塊還有很多種,例如ggplot、bokeh、pygal、plotly等,讀者可以前往各自的官網(wǎng)查看詳細(xì)的文檔說(shuō)明,相信讀者也會(huì)喜歡上其中的幾個(gè)模塊。需要注意的是,Python繪圖的核心模塊是matplotlib,其他模塊的繪圖多多少少都會(huì)依賴于該模塊,所以讀者一定要牢牢掌握matplotlib模塊中的重要知識(shí)點(diǎn)。
本章一共講解了10種常用的統(tǒng)計(jì)圖形,為了使讀者方便記憶這些繪圖函數(shù)和“方法”,特將本文涉及的繪圖函數(shù)匯總?cè)缦拢?
第六章Python數(shù)據(jù)可視化_第34張圖片


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦?。?!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 德化县| 神池县| 西贡区| 客服| 海阳市| 资阳市| 德惠市| 普宁市| 城口县| 沐川县| 虹口区| 宾阳县| 衡东县| 惠东县| 玉林市| 定边县| 青川县| 龙口市| 玛多县| 沅江市| 阳谷县| 林州市| 左云县| 溆浦县| 吴旗县| 濉溪县| 和林格尔县| 永定县| 南开区| 尉氏县| 丹巴县| 龙井市| 宁河县| 绥滨县| 大宁县| 鄯善县| 永济市| 屯门区| 普安县| 惠东县| 武强县|