day-044-Matplotlib进阶-高级图表

Day 44:Matplotlib 进阶------统计图表与3D绘图

柱状图、折线图、饼图已经熟练了。今天学更有"分析味"的图表:箱线图(看分布)、小提琴图(看分布形状)、六边形热力图(大数据散点)、以及 Matplotlib 的 3D 功能。


一、箱线图 boxplot()------一眼看清数据分布

箱线图是数据分析和论文中最常用的统计图之一,能同时展示中位数、四分位数、异常值。

python 复制代码
import matplotlib.pyplot as plt
import numpy as np

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

np.random.seed(42)

# 模拟数据:四个班级的考试成绩
class_A = np.random.normal(75, 10, 50)   # 平均75,标准差10
class_B = np.random.normal(80, 8, 50)    # 平均80,标准差8
class_C = np.random.normal(70, 15, 50)   # 平均70,标准差15(离散大)
class_D = np.random.normal(85, 12, 50)   # 平均85,标准差12

data = [class_A, class_B, class_C, class_D]
labels = ["一班", "二班", "三班", "四班"]

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# --- 图1:基础箱线图 ---
bp = axes[0].boxplot(data, labels=labels, patch_artist=True, showmeans=True)

# 配色
colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4"]
for patch, color in zip(bp["boxes"], colors):
    patch.set_facecolor(color)
    patch.set_alpha(0.7)

axes[0].set_ylabel("考试成绩", fontsize=12)
axes[0].set_title("班级成绩箱线图", fontsize=14, fontweight="bold")
axes[0].grid(True, alpha=0.3, axis="y")

# --- 图2:横向箱线图 + 散点叠加 ---
bp2 = axes[1].boxplot(data, labels=labels, patch_artist=True,
                      vert=False, showmeans=True,
                      meanprops=dict(marker="D", markerfacecolor="red", markersize=8))

for patch, color in zip(bp2["boxes"], colors):
    patch.set_facecolor(color)
    patch.set_alpha(0.5)

# 叠加原始数据点
for i, (d, color) in enumerate(zip(data, colors), 1):
    jitter = np.random.normal(0, 0.04, len(d))  # 加抖动避免重叠
    axes[1].scatter(d, i + jitter, alpha=0.4, s=20, color=color, edgecolor="white", zorder=3)

axes[1].set_xlabel("考试成绩", fontsize=12)
axes[1].set_title("横向箱线图 + 原始数据点", fontsize=14, fontweight="bold")
axes[1].grid(True, alpha=0.3, axis="x")

plt.tight_layout()
plt.show()

箱线图怎么读?

复制代码
        ┬ ─── 最大值(上边缘)
        │
        │     ┬ ─── 上四分位数 Q3(75%)
        │     │
        │  ───┼─── ─── 中位数(50%)
        │     │
        │     ┴ ─── 下四分位数 Q1(25%)
        │
        ┴ ─── 最小值(下边缘)
        ○ ─── 异常值(离群点)

二、小提琴图 violinplot()------箱线图的升级版

小提琴图 = 箱线图 + 密度曲线。既能看到统计量,又能看到数据分布形状。

python 复制代码
fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# --- 图1:基础小提琴图 ---
vp = axes[0].violinplot(data, positions=[1, 2, 3, 4], showmeans=True, showmedians=True)

for i, body in enumerate(vp["bodies"]):
    body.set_facecolor(colors[i])
    body.set_alpha(0.7)

axes[0].set_xticks([1, 2, 3, 4])
axes[0].set_xticklabels(labels)
axes[0].set_ylabel("考试成绩", fontsize=12)
axes[0].set_title("小提琴图", fontsize=14, fontweight="bold")
axes[0].grid(True, alpha=0.3, axis="y")

# --- 图2:箱线图 vs 小提琴图对比 ---
# 同数据,一半箱线图一半小提琴图
data_combined = np.concatenate(data)
labels_combined = np.repeat(labels, [len(d) for d in data])

axes[1].boxplot(data, labels=labels, patch_artist=True, widths=0.3,
                positions=np.arange(1, 5) - 0.15, showfliers=False)

vp2 = axes[1].violinplot(data, positions=np.arange(1, 5) + 0.15, showmedians=True)
for i, body in enumerate(vp2["bodies"]):
    body.set_facecolor(colors[i])
    body.set_alpha(0.5)

axes[1].set_xticks([1, 2, 3, 4])
axes[1].set_xticklabels(labels)
axes[1].set_title("箱线图(左) + 小提琴图(右) 同框对比", fontsize=14, fontweight="bold")
axes[1].grid(True, alpha=0.3, axis="y")

plt.tight_layout()
plt.show()

三、hexbin()------海量散点的高效可视化

普通散点图数据一多就糊成一片。hexbin() 用六边形格子统计每个区域的数据密度。

python 复制代码
np.random.seed(42)
n = 10000  # 一万个点

# 模拟有相关性的双变量数据
mean = [0, 0]
cov = [[1, 0.7], [0.7, 1]]
x, y = np.random.multivariate_normal(mean, cov, n).T

fig, axes = plt.subplots(1, 3, figsize=(16, 5))

# --- 普通散点图 ---
axes[0].scatter(x, y, s=1, alpha=0.3, color="#5B9BD5")
axes[0].set_title(f"普通散点图 (n={n})\n糊成一片")
axes[0].set_xlabel("X")
axes[0].set_ylabel("Y")
axes[0].grid(True, alpha=0.3)

# --- hexbin 六边形热力图 ---
hb = axes[1].hexbin(x, y, gridsize=40, cmap="YlOrRd", mincnt=1)
plt.colorbar(hb, ax=axes[1], label="数据点数", shrink=0.8)
axes[1].set_title("hexbin 六边形密度图\n密度分布一目了然")
axes[1].set_xlabel("X")
axes[1].set_ylabel("Y")

# --- 带等高线的 hexbin ---
axes[2].hexbin(x, y, gridsize=40, cmap="Blues", mincnt=1)

# 叠加 KDE 等高线(用 scipy)
from scipy.stats import gaussian_kde
kde = gaussian_kde(np.vstack([x, y]))
xi, yi = np.mgrid[-4:4:100j, -4:4:100j]
zi = kde(np.vstack([xi.flatten(), yi.flatten()])).reshape(xi.shape)
axes[2].contour(xi, yi, zi, levels=6, colors="red", linewidths=1.5, alpha=0.7)

axes[2].set_title("hexbin + KDE 等高线")
axes[2].set_xlabel("X")
axes[2].set_ylabel("Y")

plt.tight_layout()
plt.show()

四、3D 绘图入门

Matplotlib 可以画 3D 图,虽然不如专业工具强大,但日常够用。

python 复制代码
# 导入 3D 模块
from mpl_toolkits.mplot3d import Axes3D  # 虽未显式用但必须导入

4.1 3D 曲线

python 复制代码
fig = plt.figure(figsize=(14, 5))

# --- 3D 螺旋线 ---
ax1 = fig.add_subplot(1, 2, 1, projection="3d")

t = np.linspace(0, 4 * np.pi, 200)
x = np.sin(t)
y = np.cos(t)
z = t

ax1.plot(x, y, z, "b-", linewidth=2)
ax1.set_xlabel("X")
ax1.set_ylabel("Y")
ax1.set_zlabel("Z")
ax1.set_title("3D 螺旋线", fontsize=12, fontweight="bold")

# --- 3D 散点图 ---
ax2 = fig.add_subplot(1, 2, 2, projection="3d")

np.random.seed(42)
n = 300
xs = np.random.randn(n)
ys = np.random.randn(n)
zs = xs**2 + ys**2 + np.random.randn(n) * 0.5

sc = ax2.scatter(xs, ys, zs, c=zs, cmap="viridis", s=20, alpha=0.7)
plt.colorbar(sc, ax=ax2, shrink=0.6, label="Z值")
ax2.set_xlabel("X")
ax2.set_ylabel("Y")
ax2.set_zlabel("Z = X² + Y² + noise")
ax2.set_title("3D 散点图", fontsize=12, fontweight="bold")

plt.tight_layout()
plt.show()

4.2 3D 曲面图

python 复制代码
# 曲面图 plot_surface
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))   # 涟漪函数

fig = plt.figure(figsize=(14, 5))

# --- 曲面图 ---
ax1 = fig.add_subplot(1, 2, 1, projection="3d")
surf = ax1.plot_surface(X, Y, Z, cmap="viridis", alpha=0.85,
                         linewidth=0, antialiased=True)
plt.colorbar(surf, ax=ax1, shrink=0.6, label="Z值")
ax1.set_xlabel("X")
ax1.set_ylabel("Y")
ax1.set_zlabel("Z")
ax1.set_title("plot_surface 曲面图", fontsize=12, fontweight="bold")

# --- 线框图 ---
ax2 = fig.add_subplot(1, 2, 2, projection="3d")
ax2.plot_wireframe(X, Y, Z, rstride=5, cstride=5, color="steelblue", alpha=0.6, linewidth=0.5)
ax2.set_xlabel("X")
ax2.set_ylabel("Y")
ax2.set_zlabel("Z")
ax2.set_title("plot_wireframe 线框图", fontsize=12, fontweight="bold")

plt.tight_layout()
plt.show()

4.3 3D 柱状图

python 复制代码
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection="3d")

# 模拟 5天的4种产品销售数据
days = np.arange(5)
products = np.arange(4)
data_3d = np.random.randint(10, 100, (5, 4))

colors_3d = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#FFEAA7"]

_x = np.arange(5)   # 天数
_y = np.arange(4)   # 产品
_xx, _yy = np.meshgrid(_x, _y)
x_flat, y_flat = _xx.ravel(), _yy.ravel()
z_flat = np.zeros_like(x_flat)
dx = dy = 0.6
dz = data_3d.T.ravel()

# 每个柱子按产品颜色
bar_colors = np.repeat(colors_3d, 5)

ax.bar3d(x_flat, y_flat, z_flat, dx, dy, dz, color=bar_colors, alpha=0.7, edgecolor="white")
ax.set_xlabel("天数")
ax.set_ylabel("产品")
ax.set_zlabel("销量")
ax.set_xticks(_x)
ax.set_yticks(_y)
ax.set_yticklabels(["手机", "电脑", "平板", "耳机"])
ax.set_title("3D 柱状图:5天 × 4产品", fontsize=14, fontweight="bold")

plt.tight_layout()
plt.show()

五、踩坑记录 🐛

现象 解决方案
箱线图中文乱码 标签出现方块 确保 rcParams 字体设置在最前面
violinplot 位置偏移 图和标签对不齐 手动指定 positions=[1,2,3...]
hexbin 颜色全一样 密度差异看不出 调整 gridsize(越小格子越大,越容易区分)
3D 图交互卡顿 旋转视角很慢 减少数据点,或用 rstride/cstride 降低精度
3D 图视角不对 默认角度看不清 ax.view_init(elev=30, azim=45) 调整仰角和方位角
scipy 未安装 gaussian_kde 报错 pip install scipy 或跳过等高线部分

六、总结

图表类型 函数 一句话用途
箱线图 boxplot() 比较组间分布差异
小提琴图 violinplot() 看分布形状+统计量
六边形热力图 hexbin() 海量散点的密度分布
3D曲线 plot() with projection="3d" 空间曲线
3D曲面 plot_surface() 函数z=f(x,y)可视化
3D柱状 bar3d() 三维数据对比

今天学完,Matplotlib 能画的图表类型你已经掌握了 90%。明天是 Matplotlib 的最终篇------综合实战,把前面 4 天的知识全部用在一个完整项目中。
第44天,打卡完成!📊


本系列是个人学习笔记,如有错误欢迎在评论区指正交流。

相关推荐
你想知道什么?14 天前
Matplotlib学习笔记
笔记·学习·matplotlib
风流 少年18 天前
数据可视化:matplotlib、pyecharts、panda、seaborn
数据挖掘·数据分析·matplotlib
fai厅的秃头姐!18 天前
Matplotlib
matplotlib
许彰午20 天前
78_Python数据可视化matplotlib
python·信息可视化·matplotlib
尘中远23 天前
【Qwt 7.0 系列】总体架构解析 —— 从单体到三库模块化的演进
qt·matplotlib·绘图·qwt·科学绘图
2501_9423895524 天前
AI才女”罗福莉加盟小米
matplotlib·sublime text·广度优先·gunicorn
留白_1 个月前
Matplotlib绘图
信息可视化·数据分析·matplotlib
MATLAB代码顾问1 个月前
Python Matplotlib数据可视化实战指南
python·信息可视化·matplotlib
星辰徐哥1 个月前
Python AI基础:Matplotlib与Seaborn数据可视化
人工智能·python·matplotlib