長條圖(Bar Chart)是常用的統計圖表。Python 有很多套件可以輕鬆地將資料繪製成長條圖。我們將介紹 Matplotlib、Seaborn、以及 Plotly Express 這三個套件。
Table of Contents
Matplotlib
Matplotlib 的 bar() 可以繪製垂直的長條圖,而 barh() 可以繪製出水平的長條圖。它們的宣告如下。不過我們在這邊只介紹幾個比較最要且常用的參數,其餘的參數請參考官網。
matplotlib.pyplot.bar(x, height, width=0.8)
- x:x 軸上的座標。型態為 float 或 array-like。
- height:每個 bar 的高度,也可以想成 y 軸的座標。型態為 float 或 array-like。
- width:每個 bar 的寬度。型態為 float 或 array-like。
matplotlib.pyplot.barh(y, width, height=0.8)
- y:y 軸上的座標。型態為 float 或 array-like。
- width:每個 bar 的長度,也可以想成 x 軸的座標。型態為 float 或 array-like。
- height:每個 bar 的寬度。型態為 float 或 array-like。
Bar Charts
下面的範例顯示如何用 bar() 繪製長條圖。
import numpy as np import matplotlib.pyplot as plt students = ['Jack', 'Mary', 'Mike', 'David'] math_scores = [78, 67, 90, 81] x = np.arange(len(students)) plt.bar(x, math_scores, color=['red', 'green', 'blue', 'yellow']) plt.xticks(x, students) plt.xlabel('Students') plt.ylabel('Math') plt.title('Final Term') plt.show()
下面的範例顯示如何用 barh() 繪製長條圖。
from matplotlib import cm cmap = cm.jet(np.linspace(0, 1, len(students))) plt.barh(x, math_scores, color=cmap) plt.yticks(x, students) plt.ylabel('Students') plt.xlabel('Math') plt.title('Final Term') plt.show()
len(students)
是 4
,而 np.arange(4)
回傳 [0, 1, 2, 3]
。所以 x
只是 x 軸上的座標。參數 color
可以指定每個 bar 的顏色。
之後,我們呼叫 xticks()
設定 x 軸的刻度上的名稱。
xlabel()
和 ylabel()
則是設定 x 軸和 y 軸上的標題。而 title()
是設定整個圖表的標題。
最後,呼叫 show()
來將圖表顯示出來。在 Notebook 中,不需要呼叫 show() 也會自動顯示圖表。
另外,如果當圖表中有很多的 bar 時,對每個 bar 設定顏色是很麻煩的事情。這時我們可以用 Matplotlib.cm 來產生一個顏色的 array。cm 是 color map 的縮寫。np.linspace(0, 1, 4)
可以將 [0, 1] 區間分成 4 個。所以它會回傳 [0., 0.33, 0.67, 1.]
,然後 jet()
會根據 array 中的分佈,從 jet color map 中取出顏色來。
Grouped Bar Charts
bar() 和 barh() 也可以繪製 grouped 長條圖,範例如下。
import numpy as np import matplotlib.pyplot as plt students = ['Jack', 'Mary', 'Mike', 'David'] math_scores = [78, 67, 90, 81] history_scores = [94, 71, 65, 88] x = np.arange(len(students)) width = 0.3 plt.bar(x, math_scores, width, color='green', label='Math') plt.bar(x + width, history_scores, width, color='blue', label='History') plt.xticks(x + width / 2, students) plt.ylabel('Math') plt.title('Final Term') plt.legend(bbox_to_anchor=(1,1), loc='upper left') plt.show()
與繪製長條圖一樣,不過我們要呼叫 bar() 兩次分別來繪製 math_scores
和 history_scores
。bar() 的第一個參數是 x 軸上的座標,所以繪製 history_scores
時,我們要指定座標為 x + width
。這樣 history_scores
就會被畫在 math_scores
的旁邊。然後,我們也要微調 x 軸上刻度名稱的位址,讓它可以在兩個 bar 中間。
最後,我們呼叫 legend()
來顯示右上角的說明圖示。
Stacked Bar Charts
bar() 和 barh() 也可以繪製 stacked 長條圖,範例如下。
import numpy as np import matplotlib.pyplot as plt students = ['Jack', 'Mary', 'Mike', 'David'] math_scores = [78, 67, 90, 81] history_scores = [94, 71, 65, 88] x = np.arange(len(students)) plt.bar(x, math_scores, color='blue', label='Math') plt.bar(x, history_scores, color='green', label='History', bottom=math_scores) plt.xticks(x, students) plt.xlabel('Students') plt.ylabel('Math') plt.title('Final Term') plt.legend(bbox_to_anchor=(1,1), loc='upper left') plt.show()
和 grouped 長條圖一樣,我們要呼叫 bar() 兩次來分別繪製 math_scores
和 history_scores
。在繪製 history_scores
時,因為 x 軸的座標與 math_scores
的是一樣,所以一樣傳入 x
。但,這邊我們還使用到 bottom
參數。bottom
參數使指要從 y 軸上的哪個座標開始繪製,所以我們傳入 math_scores
。這樣子 history_scores
就會從 math_scores
之後開始繪製。如果是使用 barh() 時,那就要改用 left
參數。
Error Bar Charts
Error 長條圖就是在長條圖上加上誤差棒(error bars),範例如下。
import numpy as np import pandas as pd import matplotlib.pyplot as plt df = pd.DataFrame([ ['Jack', 78, 94], ['Mary', 67, 71], ['Mike', 90, 65], ['David', 81, 88], ], columns=['Students', 'Math', 'History']) df_avg = (df['Math'] + df['History']) / 2 df_max = df[['Math', 'History']].max(axis=1) df_min = df[['Math', 'History']].min(axis=1) lower_errors = df_avg - df_min upper_errors = df_max - df_avg x = np.arange(len(df)) plt.bar(x, df_avg, color=['red', 'green', 'blue', 'yellow'], yerr=[lower_errors, upper_errors], capsize=5) plt.xticks(x, df['Students']) plt.xlabel('Students') plt.ylabel('Math') plt.title('Final Term') plt.show()
首先,我們先計算出 Math 和 History 的平均值。之後,在計算上方(upper)和下方(lower)的誤差值。再將 lower_errors
和 upper_errors
傳給參數 yerr
就可以了。而,參數 capsize
是設定誤差棒兩端的寬度。如果是使用 barh() 時,那就要改用 xerr
參數。
Seaborn
Seaborn 也是一套繪製圖表的套件。它是建構在 Matplotlib 之上,但提供高階(heigh-level)API,所以會比 Matplotlib 更易於使用。此外,我覺得繪製出來的圖表比 Matplotlib 漂亮多了。
Seaborn 的 barplot() 是用來繪製長條圖,其宣告如下。我們只有列出常用的參數,其餘的參數請參照官網。
seaborn.barplot(x=None, y=None, hue=None, data=None)
- x:繪製在 x 軸的資料。它可以參數 data 裡的 column 名稱,或是 array。
- y:繪製在 y 軸的資料。它可以參數 data 裡的 column 名稱,或是 array。
- hue:分群的資料。它可以參數 data 裡的 column 名稱,或是 array。
- data:資料。型態為 DataFrame 或 array。
Bar Charts
以下為 barplot() 的範例。
import pandas as pd import seaborn as sns df = pd.DataFrame([ ['Jack', 78], ['Mary', 67], ['Mike', 90], ['David', 81], ], columns=['Students', 'Math']) ax = sns.barplot(x='Students', y='Math', data=df) ax.set_title('Final Term')
ax = sns.barplot(x='Math', y='Students', data=df) ax.set_title('Final Term')
與 bar() 相比,barplot() 的程式碼相當地短。而且,你可以看到在範例中,我們只需要指定 column 的名稱,而不需要再直接使用操作資料,相當地方便。此外,barplot() 會根據參數 x 和 y 的資料直接決定要繪製垂直或是水平的長條圖。barplot() 還會直接使用 column 的名稱作為 x 軸與 y 軸上的標題。
如果要設定圖表的標題的話,必須要呼叫 set_title()
。
Grouped Bar Charts
barplot() 繪製 grouped 長條圖也是相當地容易,範例如下。
import pandas as pd import seaborn as sns df = pd.DataFrame([ ['Jack', 'Math', 78], ['Jack', 'History', 94], ['Mary', 'Math', 67], ['Mary', 'History', 71], ['Mike', 'Math', 90], ['Mike', 'History', 65], ['David', 'Math', 81], ['David', 'History', 88], ], columns=['Students', 'Class', 'Scores']) ax = sns.barplot(x='Students', y='Scores', hue='Class', data=df) ax.set_title('Final Term')
我們只需要在參數 hue
上設定要分群的 column 名稱即可。分群的說明圖示就會自動顯示出來。
Error Bar Charts
barplot() 預設會繪製出誤差棒,範例如下。
import pandas as pd import seaborn as sns df = pd.DataFrame([ ['Jack', 'Math', 78], ['Jack', 'History', 94], ['Mary', 'Math', 67], ['Mary', 'History', 71], ['Mike', 'Math', 90], ['Mike', 'History', 65], ['David', 'Math', 81], ['David', 'History', 88], ], columns=['Students', 'Class', 'Scores']) sns.barplot(x='Students', y='Scores', data=df)
範例中,Jack 有兩筆分數,barplot() 就會自動幫你算出平均,並繪製誤差棒。
Plotly Express
Plotly Express 也是一個圖表繪製套件,與 Seaborn 一樣地容易使用。不但如此,它還有工具列可以讓你縮放、移動等操作。
Plotly Express 的 bar() 是用來繪製長條圖,其宣告如下。bar() 有相當多的參數,我們這邊只列出常用的,其餘的請參考官網。
plotly.express.bar(data_frame=None, x=None, y=Non, title=None)
- data_frame:資料。型態為 DataFrame、array-like 或 dict。
- x:繪製在 x 軸的資料。它可以是參數 data_frame 裡的 column 名稱,或是 array-like。
- y:繪製在y 軸的資料。它可以是參數 data_frame 裡的 column 名稱,或是 array-like。
- title:圖表的標題。型態為 str。
Bar Charts
以下為 bar() 的範例。
import plotly.express as px import pandas as pd df = pd.DataFrame([ ['Jack', 78], ['Mary', 67], ['Mike', 90], ['David', 81], ], columns=['Students', 'Math']) px.bar(df, x='Students', y='Math', title='Final Term')
px.bar(df, x='Math', y='Students', title='Final Term')
我們可以在 nbviewer 看到輸出的圖表。
與 Seaborn 的 barplot() 很相似,我們只需要指定 column 的名稱即可。它也會根據資料的型態,決定要繪製垂直或是水平的長條圖。它還會用 column 的名稱作為 x 軸和 y 軸上的標題。此外,要設定圖表的標題的話,只需要將字串傳入參數 title 即可。
Grouped Bar Charts
bar() 繪製 grouped 長條圖也是相當地容易,範例如下。
import pandas as pd import plotly.express as px df = pd.DataFrame([ ['Jack', 'Math', 78], ['Jack', 'History', 94], ['Mary', 'Math', 67], ['Mary', 'History', 71], ['Mike', 'Math', 90], ['Mike', 'History', 65], ['David', 'Math', 81], ['David', 'History', 88], ], columns=['Students', 'Class', 'Scores']) px.bar(df, x='Students', y='Scores', color='Class', barmode='group', title='Final Term')
df = pd.DataFrame([ ['Jack', 78, 94], ['Mary', 67, 71], ['Mike', 90, 65], ['David', 81, 88], ], columns=['Students', 'Math', 'History']) px.bar(df, x='Students', y=['Math', 'History'], barmode='group', title='Final Term')
我們可以在 nbviewer 看到輸出的圖表。
首先,參數 barmode 要設定為 group
。然後,在參數 color 設定要分群的 column 名稱就可以了。另外一種方法是,在參數 y 設定 column 名稱的 array。可以根據資料的結構,選擇方便的方法。
Stacked Bar Charts
bar() 繪製 stacked 長條圖的方法和繪製 grouped 長條圖是一樣的,只差別在於設定參數 barmode 為 relative
。範例如下。
import pandas as pd import plotly.express as px df = pd.DataFrame([ ['Jack', 'Math', 78], ['Jack', 'History', 94], ['Mary', 'Math', 67], ['Mary', 'History', 71], ['Mike', 'Math', 90], ['Mike', 'History', 65], ['David', 'Math', 81], ['David', 'History', 88], ], columns=['Students', 'Class', 'Scores']) px.bar(df, x='Students', y='Scores', color='Class', title='Final Term'
df = pd.DataFrame([ ['Jack', 78, 94], ['Mary', 67, 71], ['Mike', 90, 65], ['David', 81, 88], ], columns=['Students', 'Math', 'History']) px.bar(df, x='Students', y=['Math', 'History'], title='Final Term')
我們可以在 nbviewer 看到輸出的圖表。
參數 barmode 預設值就是 relative
,所以只要不設定它即可。
Error Bar Charts
bar() 繪製誤差棒的方式和 Matplotlib 很像,我們必須要自己計算誤差值,範例如下。
import pandas as pd import plotly.express as px df = pd.DataFrame([ ['Jack', 78, 94], ['Mary', 67, 71], ['Mike', 90, 65], ['David', 81, 88], ], columns=['Students', 'Math', 'History']) df_avg = (df['Math'] + df['History']) / 2 df_max = df[['Math', 'History']].max(axis=1) df_min = df[['Math', 'History']].min(axis=1) px.bar(df, x='Students', y=df_avg, error_y=df_max-df_avg, error_y_minus=df_avg-df_min, title='Final Term')
我們可以在 nbviewer 看到輸出的圖表。
結論
我們介紹了三套繪製長條圖的套件,分別是 Matplotlib、Seaborn、和 Plotly Express。Seaborn 和 Plotly Express 的使用方法很相似,也都相當地簡單。你比較喜歡哪個套件繪製出來的圖表呢?