[Python] Matplotlib 圖表的繪制和美化技巧


在一張畫布中繪制多個圖表

Matplotlib模塊在繪制圖表時,默認先建立一張畫布,然后在畫布中顯示繪制的圖表。

如果想要在一張畫布中繪制多個圖表,可以使用subplot()函數將畫布划分為幾個區域,然后在各個區域中分別繪制不同的圖表。

subplot()函數的參數為3個整型數字:

  • 第1個數字代表將整張畫布划分為幾行;
  • 第2個數字代表將整張畫布划分為幾列;
  • 第3個數字代表要在第幾個區域中繪制圖表,區域的編號規則是按照從左到右、從上到下的順序,從1開始編號。

演示代碼如下:

import matplotlib.pyplot as plt

# 如果值中有中文字符,則必須在繪制圖表前加上這兩行代碼
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
x = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
y = [50, 45, 65, 76, 75, 85, 55, 78, 86, 89, 94, 90]
plt.subplot(2, 2, 1)
plt.pie(y, labels = x, labeldistance = 1.1, startangle = 90, counterclock = False)
plt.subplot(2, 2, 2)

# 參數width用於設置柱子的寬度,默認值為0.8。如果設置為1,則各個柱子會緊密相連;如果設置為大於1的數,則各個柱子會相互交疊
plt.bar(x, y, width = 0.5, color = 'r')
plt.subplot(2, 2, 3)

# 參數color用於設置柱子的填充顏色,具體取值見后面的說明
plt.stackplot(x, y, color = 'r')
plt.subplot(2, 2, 4)
plt.plot(x, y, color = 'r', linestyle = 'solid', linewidth = 2, marker = 'o', markersize = 10)
plt.show()

輸出結果:

用顏色名的英文單詞或其簡寫定義的8種基礎顏色,具體見:

加圖表元素

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
x = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
y = [50, 45, 65, 76, 75, 85, 55, 78, 86, 89, 94, 90]

# 這里加了標簽
plt.bar(x, y, width=0.6, color='r', label='銷售額(萬元)')

# 這里加了標題,loc還可以是right和left
plt.title(label='銷售額對比圖', fontdict={'family': 'KaiTi', 'color': 'k', 'size': 30}, loc='center')

# 坐標上的標簽
plt.xlabel('月份', fontdict={'family': 'SimSun', 'color': 'k', 'size': 20}, labelpad=20)  
plt.ylabel('銷售額', fontdict={'family': 'SimSun', 'color': 'k', 'size': 20}, labelpad=20)  

# legend()函數用於添加圖例
plt.legend(loc='upper left', fontsize=15)

# zip() 函數用於將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的列表。
for a,b in zip(x, y):
    # text()函數的功能是在圖表坐標系的指定位置添加文本。參數ha是horizontalalignment的簡稱,相對應有va
    plt.text(x=a, y=b, s=b, ha='center', va='bottom', fontdict={'family': 'KaiTi', 'color': 'k', 'size': 20})
plt.show()

輸出結果

氣泡圖

氣泡圖是一種展示三個變量之間關系的圖表,它其實是在散點圖的基礎上升級改造而成的,在原有的x坐標和y坐標兩個變量的基礎上,引入第三個變量,並用氣泡的大小表示。

pip install openpyxl

產品銷售統計.xls 內容

產品名稱 銷售量(件) 銷售額(元) 毛利率(%)
牛仔褲 125 6800 30
連衣裙 278 5600 20
運動褲 366 7800 35
短褲 452 5800 10
短裙 365 5400 50
背帶褲 258 10000 22
半身裙 369 3600 15
闊腿褲 566 7800 8

代碼如下:

import matplotlib.pyplot as plt
import pandas as pd
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
data = pd.read_excel('產品銷售統計.xls')
n = data['產品名稱']
x = data['銷售量(件)']
y = data['銷售額(元)']
z = data['毛利率(%)']
plt.scatter(x, y, s=z * 300, color='r', marker='o')
plt.xlabel('銷售量(件)', fontdict={'family': 'Microsoft YaHei', 'color': 'k', 'size': 20}, labelpad=20)
plt.ylabel('銷售額(元)', fontdict={'family': 'Microsoft YaHei', 'color': 'k', 'size': 20}, labelpad=20)
plt.title('銷售量、銷售額與毛利率關系圖', fontdict={'family': 'Microsoft YaHei', 'color': 'k', 'size': 30}, loc='center')
for a, b, c in zip(x, y, n):
    plt.text(x=a, y=b, s=c, ha='center', va='center', fontsize=15, color='w')
plt.xlim(50, 600)
plt.ylim(2900, 11000)
plt.show()

輸出結果:

組合圖

組合圖是指在一個坐標系中繪制多張圖表,其實現方式也很簡單,在使用Matplotlib模塊中的函數繪制圖表時設置多組y坐標值即可。

銷售業績表.xls

月份 銷售額(萬元) 同比增長率
1月 ¥36.00 10%
2月 ¥25.00 8%
3月 ¥36.12 20%
4月 ¥69.30 50%
5月 ¥26.90 15%
6月 ¥32.00 11%
7月 ¥45.00 26%
8月 ¥56.00 13%
9月 ¥25.60 4%
10月 ¥36.21 5%
11月 ¥25.00 7%
12月 ¥59.00 30%
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
data = pd.read_excel('銷售業績表.xlsx')
x = data['月份']
y1 = data['銷售額(萬元)']
y2 = data['同比增長率'] 
plt.bar(x, y1, color = 'c', label = '銷售額(萬元)')  
plt.legend(loc = 'upper left', fontsize = 15)  

# 使用twinx()函數為圖表添加次坐標軸
plt.twinx()  
plt.plot(x, y2, color = 'r', linewidth = 3, label = '同比增長率')  
plt.legend(loc = 'upper right', fontsize = 15)  
plt.show()

輸出結果:

直方圖

直方圖用於展示數據的分布情況,使用Matplotlib模塊中的hist()函數可以繪制直方圖

客戶年齡統計表.zip

import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
data = pd.read_excel('客戶年齡統計表.xlsx')
x = data['年齡']
plt.hist(x, bins = 9)
plt.xlim(15, 60)
plt.ylim(0, 40)
plt.title('年齡分布直方圖', fontsize = 20)
plt.xlabel('年齡')
plt.ylabel('人數')
plt.grid(b = True, linestyle = 'dotted', linewidth = 1)
plt.show()

輸出結果

雷達圖

雷達圖可以同時比較和分析多個指標。該圖表可以看成一條或多條閉合的折線,因此,使用繪制折線圖的plot()函數也可以繪制雷達圖。

汽車性能指標分值統計表.xlsx

性能評價指標 A品牌 B品牌 C品牌
動力性 1 3 10
燃油經濟性 2 6 7
制動性 1 10 5
操控穩定性 3 10 2
行駛平順性 2 6 1
通過性 4 7 2
安全性 8 2 1
環保性 9 1 3
方便性 10 3 0
舒適性 8 2 1
經濟性 4 1 10
容量性 2 2 8

代碼如下:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  
plt.rcParams['axes.unicode_minus'] = False 
data = pd.read_excel('汽車性能指標分值統計表.xlsx')

data = data.dropna(axis=1)
data = data.set_index('性能評價指標')
data = data.T
data.index.name = '品牌'

def plot_radar(data, feature):  
    columns = ['動力性', '燃油經濟性', '制動性', '操控穩定性', '行駛平順性', '通過性', '安全性', '環保性', '方便性', '舒適性', '經濟性', '容量性'] 
    colors = ['r', 'g', 'y']

    # 設置雷達圖的角度,用於平分切開一個平面
    # linspace(1,10,x) 創建1-10的等差數組,個數為 x,默認50個;endpoint參數指定是否包含終值,默認值為True,即包含終值。
    angles = np.linspace(0.1 * np.pi, 2.1 * np.pi, len(columns), endpoint = False)

    # 使雷達圖封閉起來
    angles = np.concatenate((angles, [angles[0]]))

    # figsize:指定figure的寬和高,單位為英寸;    
    figure = plt.figure(figsize = (6, 6))
    
    # 設置為極坐標格式;subplot(nrows,ncols,sharex,sharey,subplot_kw,**fig_kw)創建單個子圖,下面兩句效果相同
    ax = figure.add_subplot(111, polar=True)
   # ax = figure.add_subplot(1, 1, 1, projection = 'polar')
    
    for i, c in enumerate(feature):
        stats = data.loc[c]

        stats = np.concatenate((stats, [stats[0]]))

        ax.plot(angles, stats, '-', linewidth = 2, c = colors[i], label = str(c))
        ax.fill(angles, stats, color = colors[i], alpha = 0.75)

    # bbox_to_anchor這個參數,可以把圖例放在圖外面
    # bbox_to_anchor:表示legend的位置,前一個表示左右,后一個表示上下。
    # 當使用這個參數時。loc將不再起正常的作用,ncol=3表示圖例三列顯示。
    ax.legend(loc = 4, bbox_to_anchor = (1.15, -0.07))

    
    #設置極軸范圍
    ax.set_ylim(0,10)
    # ax.set_yticklabels([2, 4, 6, 8, 10])

    # 添加每個特質的標簽
    columns = np.concatenate((columns, [columns[0]]))
    ax.set_thetagrids(angles*180/np.pi, columns, fontsize = 12)

    #添加標題
    plt.title('汽車性能指標雷達圖')

    plt.show()
    return figure
figure = plot_radar(data, ['A品牌', 'B品牌', 'C品牌'])
# figure = plot_radar(data, ['B品牌'])

樹狀圖

樹狀圖通過矩形的面積、排列和顏色直觀地展示多個項目的數據比例關系。要繪制該圖表,需結合使用Matplotlib模塊與squarify模塊。

import squarify as sf
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
x = ['上海', '北京', '重慶', '成都', '南京', '青島', '長沙', '武漢', '深圳']  
y = [260, 45, 69, 800, 290, 360, 450, 120, 50] 
colors = ['lightgreen', 'pink', 'yellow', 'skyblue', 'cyan', 'silver', 'lightcoral', 'orange', 'violet']
percent = ['11%', '2%', '3%', '33%', '12%', '15%', '18%', '5%', '2%']
chart = sf.plot(sizes = y, label = x, color = colors, value = percent, edgecolor = 'white', linewidth = 2)
plt.title(label = '城市銷售額分布及占比圖',fontdict = {'family' : 'KaiTi', 'color' : 'k', 'size' : 25})
plt.axis('off')
plt.show()

箱形圖

箱形圖是一種用於展示數據的分布情況的統計圖,因形狀如箱子而得名。使用Matplotlib模塊中的boxplot()函數可以繪制箱形圖。

數據

日期 成都 上海 北京 重慶 南京
1月1日 25 50 52 25 50
1月2日 12 58 56 26 56
1月3日 26 60 100 78 58
1月4日 23 78 125 45 87
1月5日 18 36 108 46 50
1月6日 15 69 100 50 60
1月7日 19 41 85 53 26
1月8日 20 52 85 61 36
1月9日 26 53 87 87 69
1月10日 27 69 86 25 78
1月11日 28 78 45 16 75
1月12日 54 80 78 69 80
1月13日 50 52 73 68 81
1月14日 51 26 62 45 45
1月15日 52 28 65 40 65
1月16日 36 57 90 50 63
1月17日 38 56 96 60 69
1月18日 45 89 94 36 64
1月19日 40 84 25 52 65
1月20日 41 85 36 54 45
1月21日 26 80 68 58 52
1月22日 29 75 78 56 59
1月23日 36 50 70 52 80
1月24日 33 25 52 57 29
1月25日 31 36 51 69 36
1月26日 15 64 58 54 29
1月27日 18 56 68 25 90
1月28日 25 54 78 36 78
1月29日 14 50 90 78 71
1月30日 39 44 95 56 75
1月31日 48 49 84 25 76
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
data = pd.read_excel('1月銷售統計表.xlsx')
x1 = data['成都']
x2 = data['上海']
x3 = data['北京']
x4 = data['重慶']
x5 = data['南京']
x = [x1, x2, x3, x4, x5]
labels = ['成都', '上海', '北京', '重慶', '南京']

# 參數vert用於設置箱形圖的方向,True表示縱向展示,False表示橫向展示;參數showmeans用於設置是否顯示均值,True表示顯示均值,False表示不顯示均值。
plt.boxplot(x, vert = True, widths = 0.5, labels = labels, showmeans = True )
plt.title('各地區1月銷售額箱形圖', fontsize = 20)
plt.ylabel('銷售額(萬元)')
plt.show()

箱形圖中的5條橫線和1個點所代表的含義如下:

  • 下限:指所有數據中的最小值;
  • 下四分位數:又稱“第一四分位數”,指將所有數據從小到大排列后第25%的值;
  • 中位數:又稱“第二四分位數”,指將所有數據從小到大排列后第50%的值;
  • 上四分位數:又稱“第三四分位數”,指將所有數據從小到大排列后第75%的值;
  • 上限:指所有數據中的最大值;
  • 點:指所有數據的平均值。

玫瑰圖

玫瑰圖可反映多個維度的數據,它將柱形圖轉化為餅圖,在圓心角相同的情況下,以扇面長度展示指標大小。要繪制玫瑰圖,也要用到繪制柱形圖的bar()函數。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']   
plt.rcParams['axes.unicode_minus'] = False

# 將風速的分布設置為4個區間
index = ['0~0.5', '0.6~2.0', '2.1~4.0', '4.1~6.0']

# 設置了16個方向
columns = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']

# seed()函數用於產生相同的隨機數
np.random.seed(0)

# 創建一個4行16列的DataFrame,其中的數據是30~300范圍內的隨機數,行標簽為第6行代碼設置的風速分布區間,列標簽為第7行代碼設置的方向。
data = pd.DataFrame(np.random.randint(30, 300, (4, 16)), index = index, columns = columns)
N = 16

# 生成16個方向的角度值
theta = np.linspace(0, 2 * np.pi, N, endpoint = False)

# 用於計算扇面的寬度
width = np.pi / N 
labels = list(data.columns) 
plt.figure(figsize = (6, 6))
ax = plt.subplot(1, 1, 1, projection = 'polar')
for i in data.index:
    radius = data.loc[i] 
    # 使用bar()函數繪制玫瑰圖中的16根柱子,也就是扇面,參數bottom用於設置每根柱子底部的位置,這里設置為0.0,表示從圓心開始繪制。
    ax.bar(theta, radius, width = width, bottom = 0.0, label = i, tick_label = labels)

# 設置0°的方向為“N”,即北方
ax.set_theta_zero_location('N') 

# 設置按逆時針方向排列各個柱子
ax.set_theta_direction(-1)    
plt.title('各方向風速頻數玫瑰圖', fontsize = 20)
plt.legend(loc = 4, bbox_to_anchor = (1.3, 0.2)) 
plt.show()

更多可參考:
[Python] 莖葉圖和復合餅圖的畫法 https://www.cnblogs.com/feily/p/14429244.html


免責聲明!

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



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