數據分析與挖掘 – 08圖形繪製

一 圖的基本構成

Matplotlib是數據可視化工作中,最常用的一個可視化庫。Matplotlib有非常多的圖形,我們很難在短時間內將其掌握,所以我們首先要掌握的是畫圖的思路和常用的一些圖形。創建一個圖的步驟大致可以分為9步,當然這9步並不是每一次都需要,只要你知道一個完整的圖形可以有這麼多的步驟就可以。每一個步驟對應著一個操作和操作它的函數。

  1. 導入模組:import matplotlib.pyplot as plt
  2. 定義影像窗口:plt.figure()
  3. 畫圖:plt.plot(x, y)
  4. 定義坐標軸範圍:x軸:plt.xlim()/y軸:plt.ylim() lim其實就是limit的縮寫
  5. 定義坐標軸名稱:x軸:plt.xlabel()/plt.ylabel()
  6. 定義坐標軸刻度及名稱:plt.xticks()/plt.yticks()
  7. 設置影像邊框顏色:ax = plt.gca() ax.spines[].set_color()
  8. 調整刻度位置:ax.xaxis.set_ticks_position()/ax.yaxis.set_ticks_position()
  9. 調整邊框(坐標軸)位置:ax.spines[].set_position()

下面請跟隨我的程式碼一起來畫一個圖感受一下吧!

import numpy as np
import matplotlib.pyplot as plt

# np.linspace將會在-5到5的區間內生成100個數,注意這個是均勻分布的
x = np.linspace(-5, 5, 100)

# 根據x的值,經過計算生成y1和y2的值
y1 = 2 * x + 1
y2 = x ** 2

# 畫圖
plt.plot(x, y1)
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')

# 顯示
plt.show()

這樣我們就畫出來一個簡單的圖形了,接下來我們繼續在剛剛畫的這個圖形中添加一些元素。我們要做的事情就是重新定義坐標軸的名稱,在定義坐標軸的名稱的時候,我們會遇到一個問題,就是中文顯示 的問題,這個問題是繞不過去的問題。

對於Windows系統的同學只需在程式碼中添加如下程式碼:

# 解決中文顯示問題
font = {"family" : "SimHei",
 "size" : "20"}
plt.rc("font", **font)

對於mac系統的同學來說,稍微有點麻煩,在terminal裡面輸入:fc-list :lang=zh,如果顯示command not found,那麼我們需要執行一個安裝命令:conda install fontconfig,然後輸入y確認就可以自動安裝好了,最後再一次輸入fc-list :lang=zh,就可以查看字體了,然後我們在程式碼中添加下面一行程式碼:

plt.rcParams["font.family"] = 'Arial Unicode MS'

下面讓我們一起來把這個繪圖完善起來,程式碼如下:

import numpy as np
import matplotlib.pyplot as plt

# np.linspace將會在-5到5的區間內生成100個數,注意這個是均勻分布的
x = np.linspace(-5, 5, 100)

# 根據x的值,經過計算生成y1和y2的值
y1 = 2 * x + 1
y2 = x ** 2

# font = {"family" : "SimHei",
#  "size" : "20"}
# plt.rc("font", **font)
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 設置畫布大小
plt.figure(figsize=(8, 5))

# 畫圖
plt.plot(x, y1)
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')

# 設置坐標軸範圍
plt.xlim((-3, 5))
plt.ylim((-4, 5))

# 設置坐標軸名稱
plt.xlabel('我是x軸')
plt.ylabel('我是y軸')

# 顯示
plt.show()

我們看到,在坐標軸上還會有一些刻度的存在,我們只需要在上邊的程式碼後邊加入一段程式碼,就可以進行刻度的修改了:

new_ticks = np.linspace(-1, 2, 5)
# 設置坐標軸的刻度
plt.xticks(new_ticks)
plt.yticks([-2, -1.8, -1, 1.22, 3], ["北京", "天津", "河北", "東北", "山東"])

除此之外,我們還可以做一些圖形邊框上的修改,在本章最開始我們已經說過關於圖形邊框修改的方法了,我們只需要把下面的程式碼添加至末尾即可:

# 添加邊框
ax = plt.gca()
# 修改右側顏色
ax.spines["right"].set_color("green")
# 修改左側顏色
ax.spines["left"].set_color("orange")
# 修改頂部顏色
ax.spines["top"].set_color("yellow")
# 修改底部顏色
ax.spines["bottom"].set_color("purple")

一起來看一下現實的效果怎麼樣
image.png
這裡需要注意的是,如果上下左右只操作其中的左側和底部,那麼其他兩條線將仍然默認是黑色,還有另外一個小技巧,我們上面的圖形總是在一個方框中顯示,我們可以把右側和頂部的線條不設置顏色,這樣看起來就與我們平時的坐標軸看起來一個樣子了,也就是把設置邊框的程式碼修改為:

ax.spines["right"].set_color("none")
ax.spines["top"].set_color("none")
plt.show()

修改之後看起來就好多了
image.png
在數學中,我們的圖形有時是十字的樣式,那下面我們一起來看一下,如何修改邊框的位置,程式碼其實也很簡單,我們首先來修改一下x軸對應y軸的位置,完整的程式碼如下:

import numpy as np
import matplotlib.pyplot as plt

# np.linspace將會在-5到5的區間內生成100個數,注意這個是均勻分布的
x = np.linspace(-5, 5, 100)

# 根據x的值,經過計算生成y1和y2的值
y1 = 2 * x + 1
y2 = x ** 2

# font = {"family" : "SimHei",
#  "size" : "20"}
# plt.rc("font", **font)
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 設置畫布大小
plt.figure(figsize=(8, 5))

# 畫圖
plt.plot(x, y1)
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')

# 設置坐標軸範圍
plt.xlim((-3, 5))
plt.ylim((-4, 5))

# 設置坐標軸名稱
plt.xlabel('我是x軸')
plt.ylabel('我是y軸')

# 設置坐標軸的刻度
plt.xticks(np.linspace(-1, 2, 5))
plt.yticks([-2, -1.8, -1, 1.22, 3], ["北京", "天津", "河北", "東北", "山東"])

# 添加邊框
ax = plt.gca()
# 修改右側顏色
ax.spines["right"].set_color("none")
# 修改左側顏色
ax.spines["left"].set_color("orange")
# 修改頂部顏色
ax.spines["top"].set_color("none")
# 修改底部顏色
ax.spines["bottom"].set_color("purple")

# 設置x軸的位置
ax.xaxis.set_ticks_position("bottom")
ax.spines["bottom"].set_position(("data", 0))
# 設置y軸的位置
ax.yaxis.set_ticks_position("left")
ax.spines["left"].set_position(("data", 0))

# 顯示
plt.show()

這樣就大功告成了,最後再來看一下現實的圖形
image.png
最後在畫圖時我們可以使用label參數給圖片添加一個圖例說明,最後使用legend顯示出來,最終程式碼如下:

import numpy as np
import matplotlib.pyplot as plt

# np.linspace將會在-5到5的區間內生成100個數,注意這個是均勻分布的
x = np.linspace(-5, 5, 100)

# 根據x的值,經過計算生成y1和y2的值
y1 = 2 * x + 1
y2 = x ** 2

# font = {"family" : "SimHei",
#  "size" : "20"}
# plt.rc("font", **font)
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 設置畫布大小
plt.figure(figsize=(8, 5))

# 畫圖
plt.plot(x, y1, label='y1圖例說明')
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--', label='y2圖例說明')

# 設置坐標軸範圍
plt.xlim((-3, 5))
plt.ylim((-4, 5))

# 設置坐標軸名稱
plt.xlabel('我是x軸')
plt.ylabel('我是y軸')

# 設置坐標軸的刻度
plt.xticks(np.linspace(-1, 2, 5))
plt.yticks([-2, -1.8, -1, 1.22, 3], ["北京", "天津", "河北", "東北", "山東"])

# 添加邊框
ax = plt.gca()
# 修改右側顏色
ax.spines["right"].set_color("none")
# 修改左側顏色
ax.spines["left"].set_color("orange")
# 修改頂部顏色
ax.spines["top"].set_color("none")
# 修改底部顏色
ax.spines["bottom"].set_color("purple")

# 設置x軸的位置
ax.xaxis.set_ticks_position("bottom")
ax.spines["bottom"].set_position(("data", 0))
# 設置y軸的位置
ax.yaxis.set_ticks_position("left")
ax.spines["left"].set_position(("data", 0))

# fontdict 是對字體大小和顏色進行設置,如果這裡會對原圖有遮擋,我們可以重新設置畫布大小
plt.text(1, -1, "這是我對圖片添加的一段說明", fontdict={"size": 12, "color": "r"})

# 顯示
plt.legend(loc='lower right')  # 圖例說明沒有參數則默認在右上角
plt.show()

二 繪製統計圖形

1 柱狀圖

在實際的企業應用中,我們要掌握多種圖形的繪製,並且深度結合自己的應用場景,用合適的圖形來展示適合它的數據場景,使得數據更具有說明力。

首先我們來學習一下bar()函數,它的功能是在x軸上繪製定性數據的分布特徵,也就是柱狀圖。使用方法是plt.bar(x,y),其中x表示在x軸上的定性數據的類別,而y表示每種定性數據的類別的數量。如果你覺得有點抽象,那我們就直接上程式碼吧。

import matplotlib.pyplot as plt

# x是刻度,y是高度
x = [1, 2, 3, 4, 5, 6, 7, 8]
y = [3, 1, 4, 5, 7, 8, 6, 4]

plt.bar(x, y)

plt.show()

程式碼非常簡單,分別定義好了x和y並且帶入函數裡面就可以了,它的現實結果其實就是一個條形圖。
image.png

2 頻率分布直方圖

與條形圖相對比的是頻率直方圖(frequency histogram),也叫做頻率分布直方圖,是統計學中表示頻率分布的圖形。在直角坐標系中,用橫軸表示隨機變數的取值,橫軸上的每個小區間對應一個組的組距,作為小矩形的底邊;縱軸表示頻率(頻數/組距=頻率),並用它作小矩形的高,以這種小矩形構成的一組圖稱為頻率直方圖。

import matplotlib.pyplot as plt
import numpy as np

x = np.random.randint(0, 10, 20)
print(x)

plt.hist(x)
plt.show()

隨機x輸出結果:[9 7 4 1 0 9 8 3 7 8 1 1 7 4 6 8 0 6 9 9]
image.png

3 餅圖

下面要學習的就是餅圖,餅圖是一種用來表示數據所佔比例最常用的圖形,它的函數是pie(),使用方法也非常的簡單,我們進行最簡單的圖形調用的時候也可以只傳一個參數,就像這樣plt.pie(x)。

import matplotlib.pyplot as plt

# 中文顯示
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 聲明類別
kinds = ['蘋果', '香蕉', '西紅柿', '西瓜']

# 這個是16進位顏色碼,你可以在網上搜索16進位顏色碼就可以獲取到所有的編碼
colors = ['#e41a1c', '#DDA0DD', '#4B0082', '#7FFFAA']

sold_nums = [4, 3, 2, 5]

# 繪製餅圖,根據圖形效果,看一下這些參數的含義吧
plt.pie(sold_nums,
        labels=kinds,
        colors=colors)

plt.show()

餅圖顯示結果
image.png

4 極線圖

接下來我們看一下極線圖的繪製方法,我們可以使用plt.polar(theta,x)這樣的方式來進行圖形的繪製,如果你之前沒接觸過這種圖形,解釋起來有一點複雜,我們直接來看一下效果吧。

import matplotlib.pyplot as plt
import numpy as np

bar_slices = 10  # 星星數量
theta = np.linspace(0.0, 2*np.pi, bar_slices, endpoint=False)
r = 30*np.random.rand(bar_slices)
print(r)

# linewidth為線條粗細,mfc為星星顏色,ms為星星大小
plt.polar(theta, r, color='chartreuse', linewidth=2, marker='*', mfc='y', ms=10)
plt.show()

r輸出結果為:[19.19557439  9.80163298 14.72266501 25.96471826 17.43950265 27.16974937
24.16166493  8.32586511  1.07374567 21.5498875 ]
image.png

5 散點圖

接下來要學習的圖形叫做散點圖,也有叫做氣泡圖的。我們可以使用plt.scatter(x,y)這樣的方式來進行圖形的繪製。關於scatter的參數:

  • x就表示x軸上的值
  • y就表示y軸上的值
  • s表示散點標記的大小,這個是可選項
  • c表示散點標記的顏色,可選項
  • cmap表示將浮點數映射成顏色的顏色映射表

讓我們通過一段程式碼的演示,來看看實踐一下這些參數。自己可以根據我的說明嘗試著修改一下這些參數。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl

a = np.random.randn(100)
b = np.random.randn(100)

"""
cmap的參數非常多,cm後面的gist_rainbow可以有很多替代
具體的可以在官網或者源程式碼中查詢使用,不過都把差別不大,就是顏色上的區別
"""
plt.scatter(a, b, s=np.power(10*a+20*b, 2),
            c=np.random.rand(100),
            cmap=mpl.cm.gist_rainbow,
            marker='o')  # marker表示散點的樣式,可以試試用o,*或者^

plt.show()

展示結果如圖所示:
image.png

6 棉棒圖

下面我們來講解一下棉棒圖的繪製方法,棉棒圖主要用來繪製離散有序的數據,使用方法是plt.stem(x,y)。關於它的參數有:

  • x:用來指定棉棒的x軸基準線上的位置。
  • y:棉棒的長度。
  • linefmt:棉棒的樣式。
  • markerfmt:棉棒末端的樣式。
  • basefmt:指定基準線的樣式。

我們直接上程式碼來看一下

import matplotlib.pyplot as plt
import numpy as np

# linspace:在0.5和2*np.pi之間返回20個均勻間隔的數據
x = np.linspace(0.5, 2 * np.pi, 20)
# randn:返回20個服從標準正態分布的樣本數據
y = np.random.randn(20)

# --是虛線,-是實線
plt.stem(x, y, linefmt='--', markerfmt='o', basefmt='-')
plt.show()

顯示結果如下圖所示:
image.png

7 箱線圖

接下來我們來繪製一下箱線圖,箱線圖的繪製方法也比較簡單,我們使用plt.boxplot(x)來實現,x就是我們要輸入的數據了。

import matplotlib.pyplot as plt
import numpy as np

x = np.random.randn(1000)
plt.boxplot(x)
plt.show()

顯示結果如下圖所示:
image.png

三 圖形參數說明

1 柱狀圖參數詳解

我們再次來看一下柱狀圖,柱狀圖在數據的可視化展示用應用的場景非常的多了,比如按照月份的商品銷量展示,銷售人員的業績統計等等場景我們都會用到。現在我在原有程式碼基礎之上加入一些新的參數,程式碼如下:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [6, 10, 4, 5, 1]

# 中文顯示
plt.rcParams["font.family"] = 'Arial Unicode MS'

plt.bar(
    # 1 柱體的標籤值
    x,
    # 2 柱體的高度
    y,
    # 3 柱體的對齊方式,兩個參數:edge或者center
    align='edge',
    # 4 顏色
    color='b',
    # 5 刻度的標籤值,用字母把x中的數字替換
    tick_label=['A', 'B', 'C', 'D', 'E'],
    # 6 透明度
    alpha=0.5
)

plt.xlabel('產品代號')
plt.ylabel('產品銷量')

# 網格設置
plt.grid(
    True,
    # 1 axis指的是對軸的設置,參數可以為x,y或者both
    axis='x',
    # 2 ls指的是網格的樣式,也可以寫成--或者:
    ls=':',
    color='r',
    alpha=0.9
)

plt.show()

顯示結果如下圖所示:
image.png

2 條形圖參數詳解

條形圖其實就是把柱狀圖橫過來放,它們的使用方法一樣,只是調用的函數不同,參數全部相同,具體程式碼如下:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [6, 10, 4, 5, 1]

# 中文顯示
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 函數改為了barh,只是添加了一個h,代表horizontal水平橫放
plt.barh(
    # 1 柱體的標籤值
    x,
    # 2 柱體的高度
    y,
    # 3 柱體的對齊方式,兩個參數:edge或者center
    align='edge',
    # 4 顏色
    color='b',
    # 5 刻度的標籤值,用字母把x中的數字替換
    tick_label=['A', 'B', 'C', 'D', 'E'],
    # 6 透明度
    alpha=0.5
)

plt.xlabel('產品代號')
plt.ylabel('產品銷量')

# 網格設置
plt.grid(
    True,
    # 1 axis指的是對軸的設置,參數可以為x,y或者both
    axis='x',
    # 2 ls指的是網格的樣式,也可以寫成--或者:
    ls=':',
    color='r',
    alpha=0.9
)

plt.show()

顯示結果如下圖所示:
image.png

3 堆積圖參數詳解

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [6, 10, 4, 5, 1]
y1 = [2, 6, 3, 4, 5]

# 中文顯示
plt.rcParams["font.family"] = 'Arial Unicode MS'

plt.figure(figsize=(8, 5))
plt.bar(
    x,
    y,
    align='center',
    color='#66c2a5',
    tick_label=['A', 'B', 'C', 'D', 'E'],
    label='男人'
)
plt.bar(
    x,
    y1,
    align='center',
    bottom=y,  # 指定哪一值在下面
    color='#8da0cb',
    label='女人'
)
plt.xlabel('城市代號')
plt.ylabel('男女比例')

plt.legend()
plt.show()

顯示結果如下圖所示:
image.png

4 堆積條形圖參數詳解

同理,堆積條形圖就是把堆積圖橫放,原來需要考慮底部的是哪一個值,現在需要思考的是左邊的是哪一個值,具體程式碼如下:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [6, 10, 4, 5, 1]
y1 = [2, 6, 3, 4, 5]

# 中文顯示
plt.rcParams["font.family"] = 'Arial Unicode MS'

plt.figure(figsize=(8, 5))
plt.barh(x, y, align='center', color='#66c2a5', tick_label=['A', 'B', 'C', 'D', 'E'], label='男人')

# 這裡修改了left 指定哪個值在這個圖的下邊
plt.barh(x, y1, align='center', left=y, color='#8da0cb', label='女人')

plt.xlabel('城市代號')
plt.ylabel('男女比例')

plt.legend()
plt.show()

顯示結果如下圖所示:
image.png

5 分塊圖參數詳解

堆積圖可以展示多數據形式上的差異,但有時不是特別明顯,這是用分塊圖就可以很直觀的比較出來。分塊圖可以分為多數據並列柱狀圖和多數據並列條形圖,我們先來一起看一下多數據並列柱狀圖,具體程式碼如下:

import matplotlib.pyplot as plt
import numpy as np

# 中文顯示
plt.rcParams["font.family"] = 'Arial Unicode MS'

x = np.arange(5)
y = [6, 10, 4, 5, 1]
y1 = [2, 6, 3, 8, 5]

bar_width = 0.35
tick_label = ['A', 'B', 'C', 'D', 'E']
plt.figure(figsize=(8, 5))

plt.bar(
    x,
    y,
    bar_width,
    color='c',
    align='center',
    label='男人',
    alpha=0.5
)

plt.bar(
    x+bar_width,
    y1,
    bar_width,
    color='b',
    align='center',
    label='女人',
    alpha=0.3
)

plt.xlabel('城市代號')
plt.ylabel('男女比例')

plt.xticks(x+bar_width/2, tick_label)

plt.legend()
plt.show()

圖形顯示結果如下圖所示:
image.png

6 多數據並列條形圖詳解

根據我們的前面的講解,你應該已經知道了,我們只需要把函數bar改為barh就可以,程式碼如下所示:

import matplotlib.pyplot as plt
import numpy as np

# 中文顯示
plt.rcParams["font.family"] = 'Arial Unicode MS'

x = np.arange(5)
y = [6, 10, 4, 5, 1]
y1 = [2, 6, 3, 8, 5]

bar_width = 0.35
tick_label = ['A', 'B', 'C', 'D', 'E']
plt.figure(figsize=(8, 5))

plt.barh(
    x,
    y,
    bar_width,
    color='c',
    align='center',
    label='男人',
    alpha=0.5,
    hatch='\/'  # 如果我們需要添加一些裝飾線可以使用hatch參數
)

plt.barh(
    x+bar_width,
    y1,
    bar_width,
    color='b',
    align='center',
    label='女人',
    alpha=0.3,
    hatch='\\'  
)

plt.xlabel('城市代號')
plt.ylabel('男女比例')

plt.xticks(x+bar_width/2, tick_label)

plt.legend()
plt.show()

圖形顯示結果如下圖所示:
image.png

7 堆積折線圖參數詳解

堆積折線圖是通過繪製不同數據集的折線圖而生成的,按照垂直方向上彼此堆疊且又不互相覆蓋的排列順序,繪製若干條折線圖而形成的組合圖形。

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(1, 6, 1)
y = [0, 4, 3, 5, 6]
y1 = [1, 3, 4, 2, 7]
y2 = [3, 4, 1, 6, 5]

labels = ['2018', '2019', '2020']
colors = ['r', 'b', 'y']

plt.stackplot(x, y, y1, y2, labels=labels, colors=colors)

plt.legend()
plt.show()

圖形顯示結果如下圖所示:
image.png

8 間斷條形圖參數詳解

間斷條形圖是在條形圖的基礎之上繪製而成的,主要用來可視化定性數據的相同指標在時間維度上的指標值的變化情況,直觀比較並展現出定性數據的相同指標的變化情況。

import matplotlib.pyplot as plt
import numpy as np

# 中文顯示
plt.rcParams["font.family"] = 'Arial Unicode MS'

plt.broken_barh(
    # 元組中第一個元素代表距離y軸的距離,第二個元素代表自身的寬度
    [(10, 20), (190, 60), (270, 80), (370, 80)],
    # 元組中第一個元素代表距離x軸的距離,第二個元素代表自身的長度
    (30, 9),
    facecolors='r'
)

plt.broken_barh(
    [(30, 80), (190, 60), (270, 80), (360, 30)],
    (10, 5),
    facecolors=('b', 'y', 'g', 'purple')
)

# 定義坐標軸的範圍
plt.xlim(0, 500)
plt.ylim(5, 50)

# 定義x軸的名稱
plt.xlabel('上課時間')

# 定義x軸的刻度
plt.xticks(np.arange(0, 361, 60))

# 定義y軸的刻度和名稱
plt.yticks([15, 25], ['一班', '二班'])

# 定義刻度的樣式
plt.grid(ls='--', lw=1, color='gray')

# 定義主題名稱
plt.title('兩個班級的上課時間')

plt.show()

圖形顯示結果如下圖所示:
image.png

9 階梯圖參數詳解

階梯圖就如其名字那樣,像一台階一樣,時而上升,時而下降,我們經常用它來展示數據的趨勢變化或周期顧慮。階梯圖經常使用在時間序列的數據的可視化任務中,比如商品的日銷量、月銷量,企業中每月的員工數量的變化等,這樣我們能夠很容易發現時序數據的波動周期和規律。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(1, 10, 10)
print(x)
y = np.sin(x)
print(y)

# 程式碼1
plt.step(x, y, color='b', where='pre', lw=2)
plt.xlim(0, 12)
plt.ylim(-1.2, 1.2)
plt.xticks(np.arange(1, 13, 1))
plt.grid(ls='--', lw=1, color='gray')
plt.show()

# 程式碼2 
plt.step(x, y, color='b', where='mid', lw=2)
plt.xlim(0, 12)
plt.ylim(-1.2, 1.2)
plt.xticks(np.arange(1, 13, 1))
plt.grid(ls='--', lw=1, color='gray')
plt.show()

# 程式碼3
plt.step(x, y, color='b', where='post', lw=2)
plt.xlim(0, 12)
plt.ylim(-1.2, 1.2)
plt.xticks(np.arange(1, 13, 1))
plt.grid(ls='--', lw=1, color='gray')
plt.show()

這裡有一個新的參數where,你可以分別運行這三段程式碼,可以看到圖形好像是在往右邊移動,顯示結果如下圖所示:
程式碼1:
image.png
程式碼2:
image.png
程式碼3:
image.png
where參數主要用來定義step應該放在哪裡,我們把圖形中的每條橫線可以看作一個step,where欄位一共有三個取值,分別是:pre,mid和post,如果我們在x為1和2的兩個位置上畫一條橫線(如上圖紅線所示),你會發現,當where=’pre’時,y取值的第一個點應該是在x第一個點左側一些,當where=’mid’時,y取值的第一個點應該是在x第一個點中間,y取值的第一個點應該是在x第一個點右側。

四 實例項目自由繪圖

1 直方圖

直方圖擅長展示區間分布,比如某一科目的考試成績,按照地區統計的人均壽命,發達國家與發展中國家人均可支配收入等等,現在我們需要繪製某個班級中Python語言考試成績的分布區間圖。

import matplotlib.pyplot as plt
import numpy as np

# 中文顯示
plt.rcParams["font.family"] = 'Arial Unicode MS'

scores = np.random.randint(0, 100, 100)
bins = range(0, 101, 10)

"""
histtype在這裡有三個參數,分別是bar,step和stepfilled
1 bar就是填滿相應顏色
2 step是階梯圖
3 histtype是生成一個默認的lineplot進行圖形填充填充,恰好這個參數的默認值就是bar
"""
plt.hist(x=scores, bins=bins, color='#3366FF', histtype='bar')
plt.xlabel('Python考試成績')
plt.ylabel('學生成績')

plt.show()

圖形顯示結果如下圖所示:
image.png
在這裡我們有必要重新再來說一下關於直方圖與柱狀圖,因為他們的樣子實在是太像了,只是柱體與柱體之間是否存在空隙,但恰恰是由於這一點,才讓它們有所區別,也讓它們分為擅長表示不同類型的數據。我們知道數據可以分為連續型數據和離散型數據,這裡我們可以對它們進行總結。直方圖擅長總結和描述連續型數據的分布,而柱狀圖更加的擅長描述和總結離散型數據的分布,所以你在未來的應用場景中,首先判斷數據的特點,然後再決定使用什麼圖形去描述這些數據。

2 堆疊直方圖

現在我們要繪製一個基於剛剛的場景之上的另外一個場景,就是我們要比較兩個班級的Python語言考試的成績,對它們的分布情況進行分別的比對,這時就需要用到堆疊直方圖。

import matplotlib.pyplot as plt
import numpy as np

# 中文顯示
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 1 分別生成兩個班級的分數
scores1 = np.random.randint(0, 100, 100)
scores2 = np.random.randint(0, 100, 100)

# 2 把兩個班級的分數放在一個列表中
x = [scores1, scores2]

# 3 選擇兩個對比較鮮明的顏色
colors = ['r', 'b']

# 4 聲明兩個標籤
labels = ['一班', '二班']

# 5 設定x軸的範圍
bins = range(0, 101, 10)

"""
新加入的參數的意義:
1 rwidth:柱體的寬度,0.0-1.0
2 stack:上下排還是左右排
"""
plt.hist(x, color=colors, histtype='bar', rwidth=1.0, stacked=False, label=labels)
plt.xlabel('Python成績分布')
plt.ylabel('人數')
plt.title('不同班級的Python成績直方圖')

plt.legend(loc=1)  # 原來用upper right這些,現在1表示右上,234分別對應逆時針旋轉位置
plt.show()

圖形顯示結果如下圖所示:
image.png

3 分裂式餅圖

餅圖是用來展示定性數據分布比例特徵的統計圖形,在數據可視化時應用的非常廣泛,我們可以通過繪製餅圖,直觀的觀察出數據的佔比情況。餅圖同樣適用於離散型數據的佔比情況,比如班級內男女性別比例,公司銷售業績每月在全年中的佔比情況等等。對於比例分布的場景,餅圖都是非常適合的。

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams["font.family"] = 'Arial Unicode MS'

labels = ['第一季度', '第二季度', '第三季度', '第四季度']
sale = [20, 40, 30, 70]
colors = ['r', 'b', 'y', 'green']

explode = (0.1, 0.1, 0.1, 0.1)

plt.pie(
    sale,
    explode=explode,  # 裂開的那條縫的寬度
    labels=labels,
    autopct='%.2f%%',  # %的精度
    startangle=10,  # 從x軸為起始位置,逆時針旋轉的角度
    shadow=True,  # 陰影
    colors=colors
)

plt.title('每一季度銷售額', loc='right')
plt.show()

圖形顯示結果如下圖所示:
image.png

4 內嵌環形餅圖

內嵌環形餅圖式使得餅圖不僅可以展示單一數據集的比例情況,還可以對比展示多數據集的分布情況。

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams["font.family"] = 'Arial Unicode MS'

development_language = ['Java', 'Python', 'C++', 'PHP', 'Scala']

weight1 = [40, 20, 30, 15, 15]
weight2 = [25, 35, 30, 12, 13]

colors = ['#FF6600', '#9966FF', '#663333', '#3399CC', '#666600']

wedges1, texts1, autotexts1 = plt.pie(
    weight1,
    autopct='%.1f%%',
    radius=1,
    pctdistance=0.85,
    colors=colors,
    textprops=dict(color='w'),
    wedgeprops=dict(width=0.3, edgecolor='w')
)

"""
餅圖的創建其實是有三個返回值的:
1 一個序列,matplotlib.patches.Wedge的實例
2 一個列表,matplotlib.text.Text的實例,是label的列表
3 一個列表,matplotlib.text.Text的實例,是數值的文本實例標籤,只有在參數autopct不為空的時候才有效
"""
print(wedges1)
print(texts1)
print(autotexts1)

wedges2, texts2, autotexts2 = plt.pie(
    weight2,
    autopct='%.1f%%',
    radius=0.75,
    pctdistance=0.75,
    colors=colors,
    textprops=dict(color='w'),
    wedgeprops=dict(width=0.5, edgecolor='b')  # 邊框
)

plt.legend(
    weight1,
    development_language,
    fontsize=5,
    title='開發語言佔比',
    loc='center left',
    bbox_to_anchor=(0.91, 0, 0.3, 1)
)

# 調整餅圖外圈中的字體
plt.setp(autotexts1, size=10, weight='bold')

# 調整餅圖內圈中的字體
plt.setp(autotexts2, size=15, weight='bold')

plt.title('開發語言使用人數比例表')
plt.show()

圖形顯示結果如下圖所示:
image.png
綜上程式碼,其實,餅圖的嵌套,就是畫兩個餅圖,不要讓他們重疊。

5 箱型圖

箱型圖主要應用在一系列測量或者比較數據的觀測中,比如學校與學校之間或者班級與班級之間的成績比較,各個運動員之間的體能比較,產品優化前和產品優化後的各項數據指標展現的結果比較等等,箱型圖是數據分析場景應用的比較多的一種數據可視化圖形。

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams["font.family"] = 'Arial Unicode MS'

# 生成正態分布數據
test1 = np.random.randn(5000)
test2 = np.random.randn(5000)

test_list = [test1, test2]

labels = ['隨機數生成1', '隨機數生成2']

colors = ['#3399FF', '#CCCCFF']

box_plot = plt.boxplot(
    test_list,
    whis=1.5,  # 上下四分位距離
    widths=0.6,
    sym='o',
    labels=labels,
    patch_artist=True,  # 是否給箱體添加顏色
    notch=True  # 是否中間v型凹陷
)

for patch, color in zip(box_plot['boxes'], colors):
    patch.set_facecolor(color)


plt.ylabel('隨機數值')
plt.title('生成器抗干擾能力的穩定性比較')

plt.grid(axis='y', ls=':', lw=1, color='gray', alpha=0.2)

plt.show()

圖形顯示結果如下圖所示:
image.png
以上是我們繪製的一些常用的圖形和一些常用的參數,當然Matplotlib繪製圖形的能力遠不止於此,但如果每一個圖形都一一講一遍的話,那麼內容會全部都由畫圖來組成了。畫圖的重點是要學習畫圖的思想,遇到問題先不要急於去畫,首先一定要選定一個合適的圖形,然後再動手。最核心的圖形無非就是那幾個常用的,我們都已經進行過了多次的練習。畫圖是數據分析、數據挖掘、AI方向的演算法工程師必備的技能,所以一定要多多的練習它們的繪製。我們還會在後續的章節中不斷的去使用這些圖形的練習。

最後會有一個小練習,請點擊下方鏈接下載題目和數據:
chapter8-1.zip