使用Matplotlib繪製堆積條形圖

2020-12-25 人工智慧遇見磐創

條形圖非常通用,易於閱讀,並且相對容易構建。

就像任何可視化一樣,條形圖也有一些缺點,例如它們的可伸縮性較差。

條形圖太多會使人感到難以閱讀,尤其是在當我們處理層次化的類別,也就是當我們有需要可視化的組和子組時,這個問題更常見。

在這種情況下,堆積條形圖是一個很好的選擇,它讓我們能更好地比較和分析數據。

在本文中,我們將探討如何使用Python的Matplotlib構建這些可視化圖形。

我將使用一個簡單的數據集來保存全球的遊戲副本的銷售數據(雖然這個數據集已經過時,但它適合我們的示例)。

import numpy as npimport pandas as pdimport matplotlib.pyplot as pltdf = pd.read_csv('../data/vgsales.csv')df.head()

我們接下來要將平臺和地區的銷售情況可視化。

將區域劃分為列很有幫助,我們只需要按「Platform」對記錄進行分組,並將NA_Sales到Global_Sales的值相加。

Groupby → Sum → Select Fields。

df_grouped = df.groupby('Platform').sum()[['NA_Sales','EU_Sales','JP_Sales','Other_Sales', 'Global_Sales']]df_grouped

數據中的值太多了,即使排除空記錄,圖表中的條形圖也會太多。

我們為每個平臺和區域繪製一個條形圖,並查看結果。

# 定義圖形fig, ax = plt.subplots(1, figsize=(16, 6))# 數字xx = np.arange(0, len(df_grouped.index))# 繪條形圖plt.bar(x - 0.3, df_grouped['NA_Sales'], width = 0.2, color = '#1D2F6F')plt.bar(x - 0.1, df_grouped['EU_Sales'], width = 0.2, color = '#8390FA')plt.bar(x + 0.1, df_grouped['JP_Sales'], width = 0.2, color = '#6EAF46')plt.bar(x + 0.3, df_grouped['Other_Sales'], width = 0.2, color = '#FAC748')# 去除spinesax.spines['right'].set_visible(False)ax.spines['top'].set_visible(False)# x y細節plt.ylabel('Millions of copies')plt.xticks(x, df_grouped.index)plt.xlim(-0.5, 31)# 網格線ax.set_axisbelow(True)ax.yaxis.grid(color='gray', linestyle='dashed', alpha=0.2)#標題和圖例plt.title('Video Game Sales By Platform and Region', loc ='left')plt.legend(['NA', 'EU', 'JP', 'Others'], loc='upper left', ncol = 4)plt.show()

正如我們所料,這張圖很難閱讀,那麼讓我們試試堆積條形圖並做一些調整。

我們在繪製之前對值進行排序,這樣可以更好地理解順序,更容易比較條形圖。我們將在「Global Sales」列中這樣操作。

## 排序值df_grouped = df_grouped.sort_values('Global_Sales')df_grouped

在前文中,我們為每個區域構建了一個簇狀條形圖,其中寬度參數和x軸上的調整幫助我們擬合了每個平臺的區域。

類似地,我們將為每個區域繪製堆積條形圖。這次,我們用bottom/left參數告訴Matplotlib正在繪製的條形圖是什麼樣。

plt.bar([1,2,3,4], [10,30,20,5])plt.bar([1,2,3,4], [3,4,5,6], bottom = [10,30,20,5])plt.show()plt.barh([1,2,3,4], [10,30,20,5])plt.barh([1,2,3,4], [3,4,5,6], left = [10,30,20,5])plt.show()

我們可以使用循環來繪製條形圖,為第一個集合中的「bottom」參數傳遞一個零列表,並為下一個區域累積以下值。

fields = ['NA_Sales','EU_Sales','JP_Sales','Other_Sales']colors = ['#1D2F6F', '#8390FA', '#6EAF46', '#FAC748']labels = ['NA', 'EU', 'JP', 'Others']# 圖形和軸fig, ax = plt.subplots(1, figsize=(12, 10))# 繪圖left = len(df_grouped) * [0]for idx, name in enumerate(fields): plt.barh(df_grouped.index, df_grouped[name], left = left, color=colors[idx]) left = left + df_grouped[name]# 標題、圖例、標籤plt.title('Video Game Sales By Platform and Region\n', loc='left')plt.legend(labels, bbox_to_anchor=([0.55, 1, 0, 0]), ncol=4, frameon=False)plt.xlabel('Millions of copies of all games')# 去除spinesax.spines['right'].set_visible(False)ax.spines['left'].set_visible(False)ax.spines['top'].set_visible(False)ax.spines['bottom'].set_visible(False)# 調整界限並繪製網格線plt.ylim(-0.5, ax.get_yticks()[-1] + 0.5)ax.set_axisbelow(True)ax.xaxis.grid(color='gray', linestyle='dashed')plt.show()

太好了,這比上一個圖更易讀。

目前我們的需求是比較平臺的總銷售和了解每個平臺的組成。

可以比較不同欄位的總數和同一條內的區域,而另一方面用不同的條形圖來比較不同的地區可能會產生很大的誤導。

在這種情況下,我們可以跨圖比較NA區域,因為每個條形圖都有相同的起始點,但是比較其他區域就不那麼容易了。以X360為例,它的JP值比PS2低,但是很難比較其他值是比Wii高還是低。

假設我們更改棧的順序,以Other Sales作為第一個條,並按Other Sales對記錄進行排序。應該更容易分辨出哪個更重要。

## 排序值df_grouped = df_grouped.sort_values('Other_Sales')fields = ['Other_Sales', 'NA_Sales','EU_Sales','JP_Sales']colors = ['#1D2F6F', '#8390FA', '#6EAF46', '#FAC748']labels = ['Others', 'NA', 'EU', 'JP']

在此可視化圖形中有兩個基本元素,即列堆棧中類別的順序和行的順序。

如果我們想要強調一個區域,可以選擇欄位對記錄排序,並使用它作為最左邊的條。

或者可以按總數對記錄進行排序,並將堆棧與具有較高值的類別排序。

堆積條形圖對於比較類別和可視化非常有用,我們可以利用它的更多優勢。

可以集中展示整體的各個部分。為了達到這個目標,我們須準備數據並計算每個地區的銷售比例。

fields = ['Other_Sales', 'NA_Sales','EU_Sales','JP_Sales']df_grouped = df.groupby('Platform').sum()# 在某些情況下,全球銷售額並不等於所有地區的總和#所以我要重新計算df_grouped['Global_Sales'] = df_grouped[fields].sum(axis=1)# 為每個地區的全球銷售額比例創建一個列for i in fields: df_grouped['{}_Percent'.format(i)] = df_grouped[i] / df_grouped['Global_Sales']df_grouped.sort_values('NA_Sales_Percent', inplace=True)df_grouped

我們幾乎可以重複之前做的操作。

# 變量labels = ['NA', 'EU', 'JP', 'Others']colors = ['#1D2F6F', '#8390FA', '#6EAF46', '#FAC748']title = 'Video Game Sales By Platform and Region\n'subtitle = 'Proportion of Games Sold by Region'def plot_stackedbar_p(df, labels, colors, title, subtitle): fields = df.columns.tolist() # 圖形和軸 fig, ax = plt.subplots(1, figsize=(12, 10))# 繪圖 left = len(df) * [0] for idx, name in enumerate(fields): plt.barh(df.index, df[name], left = left, color=colors[idx]) left = left + df[name]# 標題和副標題 plt.title(title, loc='left') plt.text(0, ax.get_yticks()[-1] + 0.75, subtitle)# 圖例 plt.legend(labels, bbox_to_anchor=([0.58, 1, 0, 0]), ncol=4, frameon=False)# 去除spines ax.spines['right'].set_visible(False) ax.spines['left'].set_visible(False) ax.spines['top'].set_visible(False) ax.spines['bottom'].set_visible(False)# 格式化x xticks = np.arange(0,1.1,0.1) xlabels = ['{}%'.format(i) for i in np.arange(0,101,10)] plt.xticks(xticks, xlabels)# 調整界限並繪製網格線 plt.ylim(-0.5, ax.get_yticks()[-1] + 0.5) ax.xaxis.grid(color='gray', linestyle='dashed')plt.show()plot_stackedbar_p(df_filter, labels, colors, title, subtitle)

這是一個很好的可視化每個地區的銷售比例的方法,也更容易比較其他類別,因為所有的條形圖都在同一點結束。

在我看來,當只有兩個類別時,用100%堆積條形圖來可視化比例會更好,因為有一個固定的起點和另一個固定的終點,所以很容易將差異可視化並比較值。

最後我們嘗試構建一個同時包含正值和負值的堆積條形圖,為本例創建一個虛擬數據幀。

# 列表sales_revenue = [1230, 1240, 1170, 1050, 1380, 1480, 1400, 1410, 1360, 1415, 1530]interest_revenue = [150, 155, 159, 176, 290, 240, 195, 146, 180, 182, 210]fixed_costs = [-810, -810, -815, -815, -780, -780, -750, -750, -750, -770, -910] variable_costs =[-380, -410, -415, -370, -520, -655, -715, -670, -515, -510, -420]# dict的列表my_dict = {'sales_revenue': sales_revenue, 'interest_revenue': interest_revenue, 'fixed_costs': fixed_costs, 'variable_costs': variable_costs}# dict到dfresult_df = pd.DataFrame(my_dict)result_df

需求是每個月有一個正的條形圖,分為銷售和利息收入,和一個負的條形圖,分為固定成本和可變成本。

我們需要把interest_revenue放在上面,所以在繪圖時使用sales_revenue作為' bottom '參數。

我們希望將fixed_costs放在頂部作為負數,將用fixed_costs作為「bottom」參數來繪製variable_cost。

plt.bar(result_df.index, result_df['interest_revenue'], bottom = result_df['sales_revenue'], color = '#5E96E9', width =0.5)plt.bar(result_df.index, result_df['variable_costs'], bottom = result_df['fixed_costs'], color = '#E17979', width =0.5)

剩下的和我們之前做的非常相似。

fig, ax = plt.subplots(1, figsize=(16, 8))plt.bar(result_df.index, result_df['sales_revenue'], color = '#337AE3', width =0.5)plt.bar(result_df.index, result_df['interest_revenue'], bottom = result_df['sales_revenue'], color = '#5E96E9', width =0.5)plt.bar(result_df.index, result_df['fixed_costs'], color = '#DB4444', width =0.5)plt.bar(result_df.index, result_df['variable_costs'], bottom = result_df['fixed_costs'], color = '#E17979', width =0.5)# x和y的極限plt.xlim(-0.6, 10.5)plt.ylim(-1600, 2000)# 去除spinesax.spines['right'].set_visible(False)ax.spines['left'].set_visible(False)ax.spines['top'].set_visible(False)ax.spines['bottom'].set_visible(False)# 網格ax.set_axisbelow(True)ax.yaxis.grid(color='gray', linestyle='dashed', alpha=0.7)# x 標籤xticks_labels = ['Jan', 'Fev', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov']plt.xticks(result_df.index , labels = xticks_labels)# 標題和圖例legend_label = ['Sales Revenue', 'Interest Revenue', 'Variable Costs', 'Fixed Costs']plt.legend(legend_label, ncol = 4, bbox_to_anchor=([1, 1.05, 0, 0]), frameon = False)plt.title('My Company - 2020\n', loc='left')plt.show()

就這樣,我們創建了很多堆積條形圖,並嘗試用了不同的應用程式來實現這種方便的可視化技術。

資源:

Matplotlib 條形圖(https://matplotlib.org/3.3.3/api/_as_gen/matplotlib.pyplot.bar.html)

Matplotlib 堆積條形圖(https://matplotlib.org/3.1.1/gallery/lines_bars_and_markers/bar_stacked.html)

Matplotlib 水平條形圖(https://matplotlib.org/3.1.1/gallery/lines_bars_and_markers/bar_stacked.html)

相關焦點

  • matplotlib庫繪製折線圖、子圖及條形圖
    前面幾節我們學習了python中numpy和pandas庫的一些常用操作,接下來幾個章節,我們學習一個非常重要的數據可視化庫matplotlib(seaborn庫也有有所涉及)。這裡我們需要知道,matplotlib庫主要繪製一些2D圖形和簡單的3D圖形。
  • 不再羨慕別人的漂亮圖表,一文學會如何用Python繪製堆積圖
    好啦,廢話少說,前幾次已經和大家詳細聊了matplotlib庫中用於繪製圖表的幾個經典函數,今天咱們繼續聊聊哦,那今天聊點什麼內容呢?就聊點深入一些的組合式圖形吧,咱們來討論一下如何繪製經典的堆積圖哦!好啦,那就開始吧!
  • 動態曲線圖(linechart)--Matplotlib繪製
    動態圖表的繪製主要在於折線圖和散點圖的繪製,我們採用的依舊還是面向對象式繪圖方式,這裡建議繪製較為複雜的圖表時多採用此方法進行繪製。完整繪圖過程如下:繪製動態曲線圖較動態氣泡圖而言,繪製過程較為簡單,主要就是折線圖和散點圖的配合使用,其他的就是圖表屬性的定製化設置了,個人能力有限,發現錯誤的同學可以留言告知啊
  • 基於Python的圖表繪圖系統matplotlib,「動態條形圖」你了解嗎?
    雖然我沒有對國力提升做出什麼不可磨滅的貢獻,但是我可以探索下動態條形圖是怎樣繪製的,應該也算是傳播知識了吧(笑哭)。之所以這麼操作,還是由於條形圖繪製過程中是從下往上畫,為了條形的排序是從下往上條形越來越長,所以採用這樣的操作。來看一下上邊截取出來的數據集繪製出來的條形圖是什麼樣子的:plt.figure(figsize=(10,6))plt.barh(dff['球隊'], dff['積分']);ok,畫出來是符合要求的條形圖!
  • Python 數據分析:Matplotlib 繪圖
    簡介Matplotlib 是 Python 提供的一個繪圖庫,通過該庫我們可以很容易的繪製出折線圖、直方圖、散點圖、餅圖等豐富的統計圖,安裝使用 pip install matplotlib 命令即可,Matplotlib 經常會與 NumPy 一起使用。
  • python使用matplotlib畫動態圖
    matplotlib是python的核心繪圖庫,是python的一個開源項目,旨在為python提供一個繪圖庫。matplotlib與numpy組合是一種可行的matlab替代方案。在可視化中matplotlib是最常使用的工具,是對數據整體判斷、效果預測不可或缺的重要模塊。
  • Python-matplotlib 學術柱狀圖繪製
    柱狀圖或條形圖在學術論文中使用的頻率還是很大的,圖中需要以不同顏色對不同數據進行區分,但當涉及黑白列印時,色彩顏色的區別度較小,導致難以理解,因此需要繪製
  • Python可視化很簡單,一文學會繪製柱狀圖、條形圖和直方圖
    matplotlib庫作為Python數據化可視化的最經典和最常用庫,掌握了它就相當於學會了Python的數據化可視化,通過前幾次呢,咱們已經討論了使用matplotlib庫中的圖表組成元素的幾個重要函數,相信大家已經學會並掌握了哦,今天呢,咱們再深入一點哦,一起來聊聊關於如何繪製柱狀圖
  • 只要簡單幾步調整,matplotlib做出來的條形圖也很好看!
    有人說matplotlib做出來的圖很低級,早起想說,那是你不會配色本文講解如何調整色以及通過添加注釋,用matplotlib做出一張好看的柱狀圖,也是「早起Python」年度報告中的一幅圖。和之前一樣先分析一下這張圖的思路首先還是先導入包與字體設置,注意這裡沒有使用全局字體而是使用臨時的字體,詳情看組件設置中字體設置文檔
  • Python-matplotlib: 散點圖的繪製
    本期推文的主要內容是散點圖的繪製教程,
  • Python matplotlib基礎繪圖函數示例
    (data,notch,position)繪製一個箱形圖plt.bar(left,height,width,bottom)繪製一個條形圖plt.barh(width,bottom,left,height)繪製一個橫向條形圖plt.polar(theta, r)繪製極坐標圖plt.pie(data
  • Matplotlib 中等高線圖(contour)的繪製
    前言在此前的文章裡,我們介紹了 Numpy 中 meshgrid 函數的應用,並提到了等高線圖的使用。
  • Python-Matplotlib 動態曲線圖繪製
    引言動態曲線圖不同於動態氣泡圖,它可以查看部分指標在一段時間內的變化趨勢,本期推文將推出動態曲線圖的 Matplotlib 繪製過程,核心過程為 折線圖 和 散點圖 的繪製,詳細過程如下:02.數據可視化動態圖表的繪製主要在於折線圖和散點圖的繪製,我們採用的依舊還是面向對象式繪圖方式,這裡建議繪製較為複雜的圖表時多採用此方法進行繪製。
  • Python可視化:學會Matplotlib這幾點就夠了!
    (3)可視化不同圖形函數常用:plt.plot(x,y,fmt,…) 繪製一個折線圖plt.boxplot(data,notch,position) 繪製一個箱形圖plt.bar(left,height,width,bottom) 繪製一個條形圖plt.barh(width,bottom,left,height) 繪製一個橫向條形圖
  • Python繪圖筆記:繪製四色散點圖和誤差條形圖
    figure1#導入繪製散點圖所需要的包import matplotlib.pyplot as pltfrom numpy.randomfrom six import iteritemsimport numpy as npimport matplotlib.pyplot as pltfrom matplotlib.lines import Line2D#每條線上繪製三個點points
  • matplotlib的Python數據可視化和探索——入門指南
    您可以使用matplotlib繪製各種圖表和可視化效果。在本教程中,我將探索matplotlib Python庫中最常見的圖。我們將首先了解手頭的數據集,然後開始使用matplotlib構建不同的圖,包括散點圖和折線圖!
  • 第92天:Python Matplotlib 進階操作
    本章節主要是 Matplotlib 和 NumPy  實際操作案例講解,matplotlib 通常與 NumPy 一起使用,提供了一種有效的 MatLab 開源替代方案,除此之外,它還可以和其他圖形工具包搭配使用。
  • pandas和matplotlib繪製簡單圖形
    1.加載包2.數據讀取3.繪圖    3.1折線圖    3.2條形圖    3.3散點圖    3.4餅圖    3.5箱體圖    3.6直方圖    3.7In [1]:%matplotlib inlineimport matplotlib.pyplot as pltimport pandas as pdIn [2]:df = pd.read_excel('data/ASV/phylum.xlsx')df
  • Python中使用matplotlib繪製灰度直方圖
    灰度直方圖在數據統計分析、圖像處理中有著比較廣泛的應用,下面就介紹一下如何在Python中使用matplotlib來繪製灰度直方圖。
  • 漂亮圖表也可信手拈來,一文學會用Python繪製堆積折線圖
    今天咱們還是接著上次的話題,繼續和大家聊聊關於Python繪圖相關的東東哦,上次已經和大家討論完了如何給自己所繪製的圖表中添加裝飾線以及修改裝飾線密度的方法,今天呢,咱們再聊點的新的東東哦,還是和大家繼續深耕Python經典的matplotlib庫哦!好啦,咱們就開始吧!