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

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

Matplotlib模塊在繪製圖表時,默認先創建一張畫布,而後在畫布中顯示繪製的圖表。python

若是想要在一張畫布中繪製多個圖表,可使用subplot()函數將畫布劃分爲幾個區域,而後在各個區域中分別繪製不一樣的圖表。數組

subplot()函數的參數爲3個整型數字:安全

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

演示代碼以下:dom

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()

輸出結果
spa

氣泡圖

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

pip install openpyxl

產品銷售統計.xls 內容code

產品名稱 銷售量(件) 銷售額(元) 毛利率(%)
牛仔褲 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()

相關文章
相關標籤/搜索