Matplotlib數據可視化(5):柱狀圖與直方圖


 

柱狀圖和直方圖是兩種非常類似的統計圖,區別在於:

  • 直方圖展示數據的分布,柱狀圖比較數據的大小。

  • 直方圖X軸為定量數據,柱狀圖X軸為分類數據。因此,直方圖上的每個條形都是不可移動的,X軸上的區間是連續的、固定的。而柱狀圖上的每個條形是可以隨意排序的,有的情況下需要按照分類數據的名稱排列,有的則需要按照數值的大小排列。

  • 直方圖柱子無間隔,柱狀圖條形有間隔

  • 直方圖條形寬度可不一,柱狀圖條形寬度須一致。柱狀圖條形的寬度因為沒有數值含義,所以寬度必須一致。但是在直方圖中,條形的寬度代表了區間的長度,根據區間的不同,條形的寬度可以不同,但理論上應為單位長度的倍數。

本篇博客將介紹matplotlib中柱狀圖和直方圖的作圖方法。

In [1]:
from matplotlib import pyplot as plt
import numpy as np
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']  # 中文字體支持
 

1 bar()與barh()

 

matplotlib中提供了bar()和barh()兩種方法畫柱狀圖,bar()用來畫垂直柱狀圖,barh()畫水平柱狀圖,兩者參數大同小異,如下所示:

 

 

2 垂直柱狀圖與水平柱狀圖

In [2]:
value= np.arange(6) ** 2
category = range(len(value))

fig = plt.figure(figsize=(8, 4))

# 垂直柱狀圖
ax1 = fig.add_subplot(121)
ax1.set_title('圖1 垂直柱狀圖')
ax1.bar(x=category, height=value)

# 垂直柱狀圖
ax2 = fig.add_subplot(122)
ax2.set_title('圖2 水平柱狀圖')
ax2.barh(y=category, width=value)  # 注意這里參數名和值的傳遞與bar()不同

plt.show()
 
 

3 顏色、透明度與邊框

In [3]:
value= np.arange(6) ** 2
category = range(len(value))

fig = plt.figure(figsize=(8, 4))

# 垂直柱狀圖
ax1 = fig.add_subplot(121)
ax1.set_title('圖1 垂直柱狀圖')
ax1.bar(x=category, height=value, 
        alpha=0.5,  # 透明度
        width=0.5,   # 每個條形的寬度
        color='yellow',  # 填充前景色
        edgecolor='red',  # 邊框顏色
        linewidth=3  # 邊框寬度
       )

# 垂直柱狀圖
ax2 = fig.add_subplot(122)
ax2.set_title('圖2 水平柱狀圖')
ax2.barh(y=category, width=value,
         alpha=1,  # 透明度
         height=0.8,   # 每個條形的寬度
        color=['green', 'red', 'yellow', 'blue', 'grey', 'magenta'],  # 填充前景色
         linewidth=3  # 不顯示邊框
       )

plt.show()
 
 

4 刻度標簽

In [4]:
value= np.arange(6) ** 2
category = range(len(value))

fig = plt.figure(figsize=(8, 4))

# 垂直柱狀圖
ax1 = fig.add_subplot(121)
ax1.set_title('圖1 垂直柱狀圖')
ax1.bar(x=category, height=value, 
        tick_label='類別'
       )

# 垂直柱狀圖
ax2 = fig.add_subplot(122)
ax2.set_title('圖2 水平柱狀圖')
ax2.barh(y=category, width=value,
         tick_label=['類1', '類2', '類3', '類4', '類5', '類6']
       )

plt.show()
 
 

5 添加誤差線

In [5]:
means = (20, 35, 30, 35, 27)  # 各組平均分
std = (2, 3, 4, 1, 2)  # 組各標准差
label = ('第一組', '第二組', '第三種', '第四組', '第五組')
bar_width = 0.4
bar_x = np.arange(len(label)) 


fig = plt.figure(figsize=(8, 4))


ax1 = fig.add_subplot(121)
bar1 = ax1.bar(x=bar_x, height=means, width=bar_width, color='green',
              yerr=std,  # 添加誤差線
              ecolor='red',  # 誤差線顏色
              capsize=5,  # 兩端線段長短
               tick_label=label
             )

ax2 = fig.add_subplot(122)
bar2 = ax2.barh(y=bar_x, width=means, height=bar_width, color='green',
              xerr=std,  # 添加誤差線
              ecolor='red',  # 誤差線顏色
              capsize=5,  # 兩端線段長短
              tick_label=label
             )

plt.show()
 
 

6 添加數據標注

In [6]:
means = (20, 35, 30, 35, 27)  # 各組平均分
std = (2, 3, 4, 1, 2)  # 組各標准差
label = ('第一組', '第二組', '第三種', '第四組', '第五組')
bar_width = 0.5
bar_x = np.arange(len(label)) 


fig = plt.figure(figsize=(10, 4),tight_layout=True)


ax1 = fig.add_subplot(121)
bar1 = ax1.bar(x=bar_x, height=means, width=bar_width, color='green', tick_label=label
             )
for b in bar1:
        height = b.get_height()
        ax1.annotate('{}'.format(height),
                    xy=(b.get_x() + b.get_width() / 2, height),
                    xytext=(0, 3),  # 3 points vertical offset
                    textcoords="offset points",color='red',
                    ha='center', va='bottom')

ax2 = fig.add_subplot(122)
bar2 = ax2.barh(y=bar_x, width=means, height=bar_width, color='green', tick_label=label
             )

for b in bar2:
        width = b.get_width()
        ax2.annotate('{}'.format(width),
                    xy=(width, b.get_y() + b.get_height() / 2),
                    xytext=(0, 3),  # 3 points vertical offset
                    textcoords="offset points",color='red',
                    ha='left', va='center')

plt.show()
 
 

7 分組柱狀圖

In [7]:
menMeans = (20, 35, 30, 35, 27)  # 男生各組平均分
womenMeans = (25, 32, 34, 20, 25)# 女生各組平均分
menStd = (2, 3, 4, 1, 2)  # 男生組各標准差
womenStd = (3, 5, 2, 3, 3) # 女生組各標准差
label = ('第一組', '第二組', '第三種', '第四組', '第五組')
bar_width = 0.4
bar_x = np.arange(len(label)) 


fig = plt.figure(figsize=(8, 4))


ax = fig.add_subplot(111)
ax.set_title('圖1 垂直柱狀圖')
bar1 = ax.bar(x=bar_x - bar_width/2,   # 設置不同的x起始位置
              height=menMeans, width=bar_width)
bar2 = ax.bar(x=bar_x + bar_width/2,   # 設置不同的x起始位置
              height=womenMeans, width=bar_width,
        )

ax.set_xlabel('組別')
ax.set_ylabel('分數')
ax.set_title('各組不同性別分數')
ax.set_xticks(range(5))
ax.set_xticklabels(label)
ax.set_yticklabels(np.arange(0, 81, 10))
ax.legend((bar1, bar2), ('男生', '女生'))

plt.show()
 
 

8 堆疊柱狀圖

In [8]:
menMeans = (20, 35, 30, 35, 27)  # 男生各組平均分
womenMeans = (25, 32, 34, 20, 25)# 女生各組平均分
menStd = (2, 3, 4, 1, 2)  # 男生組各標准差
womenStd = (3, 5, 2, 3, 3) # 女生組各標准差
label = ('第一組', '第二組', '第三種', '第四組', '第五組')
bar_width = 0.4
bar_x = np.arange(len(label)) 

fig = plt.figure(figsize=(8, 4))


ax = fig.add_subplot(111)
ax.set_title('圖1 垂直柱狀圖')
bar1 = ax.bar(x=bar_x, height=menMeans, width=bar_width)
bar2 = ax.bar(x=bar_x, height=womenMeans, width=bar_width,
        bottom=menMeans # 通過bottom參數設置起始位置, 起始位置就是下半部分(bar1)條形的高度
        )

ax.set_xlabel('組別')
ax.set_ylabel('分數')
ax.set_title('各組不同性別分數')
ax.set_xticks(range(5))
ax.set_xticklabels(label)
ax.set_yticklabels(np.arange(0, 81, 10))
ax.legend((bar1, bar2), ('男生', '女生'))

plt.show()
 
 

9 直方圖

 

直方圖的繪制是通過hist()方法完成。hist()方法參數很多,來看看主要的參數:

 

In [46]:
data_x = [131, 98, 125, 131, 124, 139, 131, 117, 128, 108, 135, 138, 131, 102, 107, 114, 119, 128, 121, 142, 127, 130, 124,
   101, 110, 116, 117, 110, 128, 128, 115, 99, 136, 126, 134, 95, 138, 117, 111, 78, 132, 124, 113, 150, 110, 117, 86,
   95, 144, 105, 126, 130, 126, 130, 126, 116, 123, 106, 112, 138, 123, 86, 101, 99, 136, 123, 117, 119, 105, 137,
   123, 128, 125, 104, 109, 134, 125, 127, 105, 120, 107, 129, 116, 108, 132, 103, 136, 118, 102, 120, 114, 105, 115,
   132, 145, 119, 121, 112, 139, 125, 138, 109, 132, 134, 156, 106, 117, 127, 144, 139, 139, 119, 140, 83, 110, 102,
   123, 107, 143, 115, 136, 118, 139, 123, 112, 118, 125, 109, 119, 133, 112, 114, 122, 109, 106, 123, 116, 131, 127,
   115, 118, 112, 135, 115, 146, 137, 116, 103, 144, 83, 123, 111, 110, 111, 100, 154, 136, 100, 118, 119, 133, 134,
   106, 129, 126, 110, 111, 109, 141, 120, 117, 106, 149, 122, 122, 110, 118, 127, 121, 114, 125, 126, 114, 140, 103,
   130, 141, 117, 106, 114, 121, 114, 133, 137, 92, 121, 112, 146, 97, 137, 105, 98, 117, 112, 81, 97, 139, 113, 134,
   106, 144, 110, 137, 137, 111, 104, 117, 100, 111, 101, 110, 105, 129, 137, 112, 120, 113, 133, 112, 83, 94, 146,
   133, 101, 131, 116, 111, 84, 137, 115, 122, 106, 144, 109, 123, 116, 111, 111, 133, 150]

fig = plt.figure(figsize=(8, 4))

ax1 = fig.add_subplot(121)
hists1 = ax1.hist(x=data_x, bins=5)  # 等距划分

ax2 = fig.add_subplot(122)
hists2 = ax2.hist(x=data_x,bins=[78,90,100,120,140,145,150])

plt.show()
 
 

hist()方法將會返回一個包含三個元素的數組,第一個元素為每個條形區間中元素的數量,第二個元素為區間的邊界,第三個元素為Patch實例化對象。

In [47]:
hists1
Out[47]:
(array([ 9., 49., 97., 77., 18.]),
 array([ 78. ,  93.6, 109.2, 124.8, 140.4, 156. ]),
 <a list of 5 Patch objects>)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM