Python 長條圖(Bar Charts)

Photo by Jonatan Pie on Unsplash
Photo by Jonatan Pie on Unsplash
長條圖(Bar Chart)是常用的統計圖表。Python 有很多套件可以輕鬆地將資料繪製成長條圖。我們將介紹 Matplotlib、Seaborn、以及 Plotly Express 這三個套件。

長條圖(Bar Chart)是常用的統計圖表。Python 有很多套件可以輕鬆地將資料繪製成長條圖。我們將介紹 Matplotlib、Seaborn、以及 Plotly Express 這三個套件。

完整程式碼可以在 下載。

Matplotlib

Matplotlibbar() 可以繪製垂直的長條圖,而 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()
Matplotlib vertical bar chart
Matplotlib vertical bar chart

下面的範例顯示如何用 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()
Matplotlib horizontal bar chart
Matplotlib horizontal bar chart

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()
Matplotlib grouped bar chart
Matplotlib grouped bar chart

與繪製長條圖一樣,不過我們要呼叫 bar() 兩次分別來繪製 math_scoreshistory_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()
Matplotlib stacked bar chart
Matplotlib stacked bar chart

和 grouped 長條圖一樣,我們要呼叫 bar() 兩次來分別繪製 math_scoreshistory_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()
Matplotlib error bar chart
Matplotlib error bar chart

首先,我們先計算出 Math 和 History 的平均值。之後,在計算上方(upper)和下方(lower)的誤差值。再將 lower_errorsupper_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')
Seaborn vertical bar chart
Seaborn vertical bar chart
ax = sns.barplot(x='Math', y='Students', data=df)
ax.set_title('Final Term')
Seaborn horizontal bar chart
Seaborn horizontal bar chart

與 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')
Seaborn grouped bar chart
Seaborn grouped bar chart

我們只需要在參數 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)
Seaborn error bar chart
Seaborn error bar chart

範例中,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')
Plotly Express vertical bar chart
Plotly Express vertical bar chart
px.bar(df, x='Math', y='Students', title='Final Term')
Plotly Express horizontal bar chart
Plotly Express horizontal bar chart

我們可以在 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')
Plotly Express grouped bar chart
Plotly Express grouped bar chart

我們可以在 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')
Plotly Express stacked bar chart
Plotly Express stacked bar chart

我們可以在 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')
Plotly Express error bar chart
Plotly Express error bar chart

我們可以在 nbviewer 看到輸出的圖表。

結論

我們介紹了三套繪製長條圖的套件,分別是 Matplotlib、Seaborn、和 Plotly Express。Seaborn 和 Plotly Express 的使用方法很相似,也都相當地簡單。你比較喜歡哪個套件繪製出來的圖表呢?

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

You May Also Like