使用Matplotlib繪製堆積條形圖

2021-01-08 人工智慧遇見磐創

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

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

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

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

在本文中,我們將探討如何使用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)

相關焦點

  • 不再羨慕別人的漂亮圖表,一文學會如何用Python繪製堆積圖
    好啦,廢話少說,前幾次已經和大家詳細聊了matplotlib庫中用於繪製圖表的幾個經典函數,今天咱們繼續聊聊哦,那今天聊點什麼內容呢?就聊點深入一些的組合式圖形吧,咱們來討論一下如何繪製經典的堆積圖哦!好啦,那就開始吧!
  • 基於Python的圖表繪圖系統matplotlib,「動態條形圖」你了解嗎?
    雖然我沒有對國力提升做出什麼不可磨滅的貢獻,但是我可以探索下動態條形圖是怎樣繪製的,應該也算是傳播知識了吧(笑哭)。之所以這麼操作,還是由於條形圖繪製過程中是從下往上畫,為了條形的排序是從下往上條形越來越長,所以採用這樣的操作。來看一下上邊截取出來的數據集繪製出來的條形圖是什麼樣子的:plt.figure(figsize=(10,6))plt.barh(dff['球隊'], dff['積分']);ok,畫出來是符合要求的條形圖!
  • Python可視化很簡單,一文學會繪製柱狀圖、條形圖和直方圖
    matplotlib庫作為Python數據化可視化的最經典和最常用庫,掌握了它就相當於學會了Python的數據化可視化,通過前幾次呢,咱們已經討論了使用matplotlib庫中的圖表組成元素的幾個重要函數,相信大家已經學會並掌握了哦,今天呢,咱們再深入一點哦,一起來聊聊關於如何繪製柱狀圖
  • matplotlib的Python數據可視化和探索——入門指南
    Matplotlib可用於Python腳本,Python和IPython外殼,Jupyter筆記本,Web應用程式伺服器以及四個圖形用戶界面工具包。」您可以使用matplotlib繪製各種圖表和可視化效果。在本教程中,我將探索matplotlib Python庫中最常見的圖。我們將首先了解手頭的數據集,然後開始使用matplotlib構建不同的圖,包括散點圖和折線圖!
  • matplotlib繪圖的核心原理講解
    最後,張三就是在分配好的不同區域上進行圖形繪製了,在一張畫布上,畫的最多的應該就是2D圖,也可以畫3D圖,如圖所示,張三在區域一畫了一個小狗,在區域二畫了一個小貓,在區域三畫了一個光頭強。對比到matplotlib中,我們在axes1中畫了一個條形圖,在axes2中畫了一個餅圖,在axes3中畫了一個折線圖。
  • 如何用matplotlib繪圖呢?
    什麼是matplotlib?使用過python做數據分析的小夥伴都知道,matplotlib是一款命令式、較底層、可定製性強、圖表資源豐富、簡單易用、出版質量級別的python 2D繪圖庫。最適合來運行matplotlib繪圖的工具是jupyter notebook,本教程也是基於該工具做實驗。這是一種交互式筆記本,在瀏覽器上運行代碼,能直接顯示運行結果和圖表,詳情可見jupyter notebook介紹。哪些圖表可以用matplotlib繪製呢?
  • Python繪圖筆記:繪製四色散點圖和誤差條形圖
    figure1#導入繪製散點圖所需要的包import matplotlib.pyplot as pltfrom numpy.random import rand#生成繪圖所需的圖紙fig, ax = plt.subplots
  • Python 繪圖庫 Matplotlib 入門教程
    >通過np.arange(100, 201)生成一個[100, 200]之間的整數數組,它的值是:[100, 101, 102, … , 200]通過matplotlib.pyplot將其繪製出來。很顯然,繪製出來的值對應了圖中的縱坐標(y軸)。而matplotlib本身為我們設置了圖形的橫坐標(x軸):[0, 100],因為我們剛好有100個數值通過plt.show()將這個圖形顯示出來這段代碼非常的簡單,運行起來也是一樣。
  • 漂亮圖表也可信手拈來,一文學會用Python繪製堆積折線圖
    今天咱們還是接著上次的話題,繼續和大家聊聊關於Python繪圖相關的東東哦,上次已經和大家討論完了如何給自己所繪製的圖表中添加裝飾線以及修改裝飾線密度的方法,今天呢,咱們再聊點的新的東東哦,還是和大家繼續深耕Python經典的matplotlib庫哦!好啦,咱們就開始吧!
  • 30分鐘入門 Matplotlib 繪圖
    Matplolib最初主要模仿Matlab的畫圖命令,但是它是獨立於Matlab的,可以自由、免費使用的繪圖包。Matplotlib依賴於之前介紹的Numpy庫來提供出色的繪圖能力。pip install matplotlib如果安裝失敗,可以使用國內的鏡像來安裝Matplotlib庫,如下所示。
  • matplotlib如何實現圖形繪製在tkinter的Canvas中?
    matplotlib如何實現圖形繪製在tkinter的Canvas中?今天番茄加速就來分享一下。下面就是最重要的tkinter和matplotlib集成部分,matplotlib提供FigureCanvasTkAgg對象,只需三行代碼,實現圖形繪製在tkinter的Canvas中:canvas_l = FigureCanvasTkAgg(figure_l, frame_l)# 用draw代替canvas_l.draw()canvas_l.get_tk_widget
  • python matplotlib畫圖教程學習:使用介紹
    本篇文章介紹matplotlib包使用時,需要掌握的一些基本概念。除了圖中顯示的紅藍線型圖和散點圖,matplotlib還能繪製柱形圖、燭型圖、餅圖、3D圖形等等各種個性化圖形,將在後續文章一一介紹。matplotlib圖形的幾個主要對象:Figure對象整個圖形即是一個Figure對象。Figure對象至少包含一個子圖,也就是Axes對象。
  • Python 繪圖,我只用 Matplotlib
    散點圖散點圖顯示兩組數據的值,如圖1-1所示。每個點的坐標位置由變量的值決定,並由一組不連接的點完成,用於觀察兩種變量的相關性。例如,身高—體重、溫度—維度。圖1-1 散點圖示例使用Matplotlib的scatter()函數繪製散點圖,其中x和y是相同長度的數組序列。
  • Python使用matplotlib繪製隨機漫步圖
    隨機漫步在本節中,我們將使用Python生成隨機漫步數據,再使用matplotlib以引入矚目的方式將這些數據呈現出來。隨機漫步是這樣行走得到的路徑:每次行走都完全隨機的,沒有明確的方向,結果是由一系列隨機決策決定的。
  • matplotlib中簡單條形圖,你了解嗎?
    就是下圖的這個樣子:圖先亮出來啦,接下來研究這個圖是怎麼畫的吧,先看一下原數據長什麼樣子:實際畫圖的流程和畫折線圖很相近,只是用到的畫圖函數不一樣,繪製條形圖的函數plt.bar():由於這只是最簡單的一個條形圖,實際上條形圖的函數plt.bar()還有不少可以探索的參數設置,和對摺線圖函數plt.plot()的探索差不多,有興趣的孩子可以自己去進行探索哦。
  • 看了這個總結,其實 Matplotlib 可視化,也沒那麼難!
    Matplotlib 可用於創建高質量的圖表和圖形,也可以用於繪製和可視化結果。matplotlib 是 Python 優秀的數據可視化第三方庫,matplotlib.pyplot 是繪製種類可視化圖形的命令子庫,相當於快捷方式 import matplotlib.pyplot as plt.
  • python學習筆記:同時畫多圖,折線圖,箱線圖,條形圖,柱狀圖等
    1.同時畫六張圖#從Matplotlib中導入了pyplot繪圖模塊from matplotlib.pyplot import *#設置相關的數值x=[1,2,3,4]y=[5,4,3,2]#創建一個圖紙(figure)figure()#使用subplot創建多個子圖,下面的subplot(2,3,1)表示創建一個包含2行3列圖表的圖紙,1表示第一張圖subplot
  • 這麼用MatPlotLib視覺化呈現數據,你值得擁有!
    這些功能廣泛應用於折線圖、柱狀圖、直方圖、餅狀圖等。案例學習如上所述,可使用Matplotlib繪製多種圖形,如散點圖、柱狀圖和直方圖。根據數據視覺化過程中的實際需求選擇圖形類型,如群組對比、定量變量對比、數據分布分析等。
  • 見識matplotlib:不常見的一面,折線圖!
    眾所周知,matplotlib是python繪圖的基礎包,能夠生成各種各樣2D或者3D的圖形,用法算是多而全的那種,下邊是matplotlib官網首頁作為例子的幾張圖,大家感受一下:什麼?醜拒?不不不,別激動!其實matplotlib一直是一個低調奢華有內涵的包,需要我們透過它樸實無華的外表認清它豐富多彩的內在,來康康這條妖嬈的曲線,有沒有感受到它的召喚?
  • Matplotlib庫繪製直方圖
    pyplot用於繪製直方圖的函數為hist( ),該函數具有一個其他繪圖函數所沒有的功能。它除了繪製直方圖外,還以元組形式返回直方圖的計算結果。事實上,hist( )函數還可以實現直方圖的計算。首先使用random.randint( )函數生成100個0~100的隨機數作為樣本。現在,我們把剛生成的樣本數據作為參數傳給hist( )函數,創建一個直方圖。例如,你想把樣本個體分到20個面元中(如未指定,默認分為10個面元),關鍵字參數bin的值為20。