首頁>技術>

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

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

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

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

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

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

import numpy as npimport pandas as pdimport matplotlib.pyplot as plt
df = 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()

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

資源:

13
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • mybatis3.5.1---1