【matplotlib 實戰】--平行座標系

wang_yb發表於2023-10-04

平行座標系是一種統計圖表,它包含多個垂直平行的座標軸,每個軸表示一個欄位,並用刻度標明範圍。透過在每個軸上找到資料點的落點,並將它們連線起來形成折線,可以很容易地展示多維資料。
隨著資料增多,折線會堆疊,分析者可以從中發現資料的特性和規律,比如發現資料之間的聚類關係。

儘管平行座標系與折線圖表面上看起來相似,但它並不表示趨勢,各個座標軸之間也沒有因果關係。
因此,在使用平行座標系時,軸的順序是可以人為決定的,這會影響閱讀的感知和判斷。較近的兩根座標軸會使對比感知更強烈。
因此,為了得出最合適和美觀的排序方式,通常需要進行多次試驗和比較。

同時,嘗試不同的排序方式也可能有助於得出更多的結論。

此外,平行座標系的每個座標軸很可能具有不同的資料範圍,這容易導致讀者的誤解。
因此,在繪製圖表時,最好明確標明每個軸上的最小值和最大值。

1. 主要元素

平行座標系是一種常用的資料視覺化方法,用於展示多個維度的資料,並透過連線這些維度的線段來揭示它們之間的關係。

它的主要元素包括:

  1. 座標軸:平行座標系通常由垂直於資料維度的座標軸組成,每個座標軸代表一個資料維度。
  2. 資料點:每個資料點在平行座標系中由一條連線各個座標軸的線段表示,線段的位置和形狀反映了資料點在各個維度上的取值。
  3. 連線線:連線線用於將同一資料點在不同維度上的線段連線起來,形成資料點的輪廓,幫助觀察者理解資料點在各個維度上的變化趨勢。

image.png

2. 適用的場景

平行座標系適用的場景有:

  • 多維資料分析:平行座標系適用於展示多個維度的資料,幫助觀察者發現不同維度之間的關係和趨勢,例如在探索資料集中的模式、異常值或相關性時。
  • 資料分類和聚類:透過觀察資料點的輪廓和分佈,可以幫助觀察者識別不同的資料類別或聚類。
  • 資料互動與過濾:平行座標系可以支援互動式資料探索和過濾,透過選擇或操作特定的座標軸或線段,可以對資料進行篩選和聚焦。

3. 不適用的場景

平行座標系不適用的場景有:

  • 資料維度過多:當資料維度過多時,平行座標系的可讀性和解釋性可能會下降,因為線段之間的交叉和重疊會導致視覺混亂。
  • 資料維度之間差異較大:如果資料在不同維度上的取值範圍差異較大,那麼線段之間的比較和分析可能會受到影響,因為較小的取值範圍可能會被較大的取值範圍所掩蓋。
  • 資料具有時間序列:平行座標系並不適用於展示時間序列資料,因為它無法準確地表示資料的時間順序。在這種情況下,其他的資料視覺化方法,如折線圖或時間軸圖,可能更適合。

4. 分析實戰

平行座標系適用於展示具有相同屬性的一系列資料,每個座標系代表一種屬性。
這次選用了國家統計局公開的教育類資料:https://databook.top/nation/A0M

選取其中幾類具有相同屬性的資料:

  1. A0M06:各級各類學校專任教師數
  2. A0M07:各級各類學校招生數
  3. A0M08:各級各類學校在校學生數
  4. A0M09:各級各類學校畢業生數

4.1. 資料來源

四個原始資料集是按照年份統計的:

fp = "d:/share/A0M06.csv"

df = pd.read_csv(fp)
df

image.png

這是教師相關統計資料,其他3個資料集的結構也類似。

4.2. 資料清理

平行座標系比較的是屬性,不需要每年的資料。
所以,對於上面4個資料集,分別提取2022年小學初中高中特殊教育相關4個屬性的資料。

import os

files = {
    "教師數": "A0M06.csv",
    "招生數": "A0M07.csv",
    "在校學生數": "A0M08.csv",
    "畢業學生數": "A0M09.csv",
}
data_dir = "d:/share"

data = pd.DataFrame()
for key in files:
    fp = os.path.join(data_dir, files[key])
    df = pd.read_csv(fp)
    df_filter = pd.DataFrame(
        [[
            key,
            df.loc[225, "value"],
            df.loc[135, "value"],
            df.loc[90, "value"],
            df.loc[270, "value"],
        ]],
        columns=["name", "小學", "初中", "高中", "特殊教育"],
    )
    data = pd.concat([data, df_filter])

data

image.png

4.3. 分析結果視覺化

平行座標系在 matplotlib 中沒有直接提供,實現起來也不難:

import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
import numpy as np

xnames = data.loc[:, "name"]
ynames = ["小學", "初中", "高中", "特殊教育"]
ys = np.array(data.iloc[:, 1:].values.tolist())
ymins = ys.min(axis=0)
ymaxs = ys.max(axis=0)
dys = ymaxs - ymins
ymins -= dys * 0.05  # Y軸的上下限增加 5% 的冗餘
ymaxs += dys * 0.05

#每個座標系的上下限不一樣,調整顯示方式
zs = np.zeros_like(ys)
zs[:, 0] = ys[:, 0]
zs[:, 1:] = (ys[:, 1:] - ymins[1:]) / dys[1:] * dys[0] + ymins[0]

fig, host = plt.subplots(figsize=(10, 4))

axes = [host] + [host.twinx() for i in range(ys.shape[1] - 1)]
for i, ax in enumerate(axes):
    ax.set_ylim(ymins[i], ymaxs[i])
    ax.spines["top"].set_visible(False)
    ax.spines["bottom"].set_visible(False)
    if ax != host:
        ax.spines["left"].set_visible(False)
        ax.yaxis.set_ticks_position("right")
        ax.spines["right"].set_position(("axes", i / (ys.shape[1] - 1)))

host.set_xlim(0, ys.shape[1] - 1)
host.set_xticks(range(ys.shape[1]))
host.set_xticklabels(ynames, fontsize=14)
host.tick_params(axis="x", which="major", pad=7)
host.spines["right"].set_visible(False)
host.xaxis.tick_top()
host.set_title("各類學校的師生數目比較", fontsize=18, pad=12)

colors = plt.cm.Set1.colors
legend_handles = [None for _ in xnames]
for j in range(ys.shape[0]):
    verts = list(
        zip(
            [x for x in np.linspace(0, len(ys) - 1, len(ys) * 3 - 2, endpoint=True)],
            np.repeat(zs[j, :], 3)[1:-1],
        )
    )
    codes = [Path.MOVETO] + [Path.CURVE4 for _ in range(len(verts) - 1)]
    path = Path(verts, codes)
    patch = patches.PathPatch(
        path, facecolor="none", lw=2, alpha=0.7, edgecolor=colors[j]
    )
    legend_handles[j] = patch
    host.add_patch(patch)

host.legend(
    xnames,
    loc="lower center",
    bbox_to_anchor=(0.5, -0.18),
    ncol=len(xnames),
    fancybox=True,
    shadow=True,
)
plt.tight_layout()
plt.show()

image.png

從圖表中,可以看出一下幾點,和我們對實際情況的印象是差不多的:

  1. 教師數量遠小於學生數量
  2. 從小學到初中,高中,學生數量不斷減少
  3. 招生數量和畢業生數量差不多

平行座標系用於比較不同資料集相同屬性

相關文章