第一章准备工作与环境搭建在开始数据可视化之前我们需要搭建一个干净、高效的 Python 环境。NumPy 是 Python 科学计算的基石提供了强大的 N 维数组对象Matplotlib 则是 Python 最著名的绘图库能够生成高质量的图表。1.1 环境安装推荐使用 Anaconda 发行版它预装了 NumPy、Matplotlib 以及 Jupyter Notebook 等常用工具。使用 pip 安装bashpip install numpy matplotlib验证安装在 Python 交互式环境或脚本中运行以下代码若无报错则安装成功。pythonimport numpy as np import matplotlib.pyplot as plt print(np.__version__) # 例如1.24.3 print(plt.__version__) # 例如3.7.21.2 核心概念Figure 与 AxesMatplotlib 的绘图逻辑建立在两个核心对象之上Figure (画布)整个图形的最外层容器可以包含一个或多个子图Axes。Axes (坐标系)我们通常所说的“图”。它包含数据区域、坐标轴、刻度、标签等。一个 Figure 可以有多个 Axes。理解这两种对象的区别是摆脱“用plt.plot画简单图”思维迈向复杂布局控制的关键。两种常用的绘图接口pyplot状态机接口 (隐式)类似于 MATLAB 风格通过plt.plot()等命令自动在当前活跃的 Axes 上绘图。适合快速探索。pythonplt.plot(x, y) plt.xlabel(x) plt.ylabel(y) plt.show()面向对象接口 (显式)更推荐尤其在复杂图表中。通过显式调用fig, ax plt.subplots()创建 Figure 和 Axes 对象然后调用ax.plot()等方法。pythonfig, ax plt.subplots() ax.plot(x, y) ax.set_xlabel(x) ax.set_ylabel(y) plt.show()第二章NumPy 在可视化中的角色Matplotlib 本身不计算数据它只负责绘制。NumPy 则负责生成、处理和转换数据。两者结合使用可以高效地探索数据模式。2.1 生成数据源NumPy 提供了丰富的函数来生成测试数据这对于学习绘图非常方便。pythonimport numpy as np import matplotlib.pyplot as plt # 1. 线性空间生成 x 轴数据 x np.linspace(0, 10, 100) # 在 [0, 10] 区间生成 100 个均匀分布的点 y1 np.sin(x) # 正弦函数 y2 np.cos(x) # 余弦函数 # 2. 随机数据模拟真实场景 data np.random.normal(loc0, scale1, size1000) # 正态分布数据 noise np.random.rand(50) * 2 - 1 # 均匀分布噪声 [-1, 1]2.2 向量化计算与绘图NumPy 的核心优势是向量化计算。它允许我们对整个数组进行操作而无需编写显式循环。这极大地提高了代码效率和可读性。python# 非向量化方式慢不推荐 x [i for i in range(10)] y [] for xi in x: y.append(xi**2) # 向量化方式快推荐 x np.arange(10) y x ** 2 # 对数组中每个元素求平方 # 绘图 plt.plot(x, y) plt.show()2.3 处理不规则数据在实际应用中数据往往是不完整的。NumPy 的np.nan(Not a Number) 配合 Matplotlib 可以优雅地处理缺失值。pythonx np.linspace(0, 10, 100) y np.sin(x) # 人为制造一段缺失数据 y[20:40] np.nan plt.plot(x, y, labelsin(x) with gap) plt.legend() plt.show() # Matplotlib 会自动跳过 np.nan 对应的点断开线条第三章基础图表绘制本章将介绍最常用的几种图表类型并解释其核心参数。3.1 折线图 (Line Plot)折线图用于显示数据随时间或有序变量变化的趋势。pythonx np.linspace(0, 2 * np.pi, 50) y_sin np.sin(x) y_cos np.cos(x) plt.figure(figsize(10, 6)) # 设置画布大小英寸 plt.plot(x, y_sin, colorblue, # 颜色 linestyle--, # 线型-, --, -., : linewidth2, # 线宽 markero, # 数据点标记o, ^, s, D, x 等 markersize4, # 标记大小 labelsin(x)) # 图例标签 plt.plot(x, y_cos, colorred, linestyle-, labelcos(x)) plt.xlabel(x (radians)) plt.ylabel(Amplitude) plt.title(Sine and Cosine Waves) plt.legend(locupper right) # 图例位置 plt.grid(True, alpha0.3) # 显示网格透明度0.3 plt.show()3.2 散点图 (Scatter Plot)散点图用于观察两个变量之间的相关性、分布以及异常值。python# 生成 200 个随机点 n 200 x np.random.randn(n) y np.random.randn(n) colors np.random.rand(n) # 随机颜色值 sizes np.random.randint(20, 200, n) # 随机点大小 plt.figure(figsize(8, 6)) sc plt.scatter(x, y, ccolors, # 颜色映射 ssizes, # 点大小 alpha0.6, # 透明度 cmapviridis) # 颜色映射方案 plt.colorbar(sc) # 显示颜色条 plt.xlabel(X) plt.ylabel(Y) plt.title(Scatter Plot with Color and Size Mapping) plt.show()3.3 柱状图 (Bar Plot)柱状图用于比较不同类别的数值。pythoncategories [A, B, C, D, E] values np.random.randint(10, 100, size5) plt.figure(figsize(8, 5)) bars plt.bar(categories, values, color[#FF9999, #66B2FF, #99FF99, #FFCC99, #FF99CC], edgecolorblack, linewidth1) # 在柱子上方添加数值标签 for bar in bars: height bar.get_height() plt.text(bar.get_x() bar.get_width()/2., height 1, f{height}, hacenter, vabottom) plt.xlabel(Category) plt.ylabel(Value) plt.title(Bar Chart Example) plt.show()水平柱状图pythonplt.barh(categories, values) # 使用 barh3.4 直方图 (Histogram)直方图用于展示连续变量的分布情况。python# 生成符合正态分布的数据 data np.random.randn(1000) plt.figure(figsize(10, 5)) # 子图1默认直方图 plt.subplot(1, 2, 1) # 1行2列第1个图 plt.hist(data, bins30, edgecolorblack, alpha0.7) plt.title(Histogram (bins30)) plt.xlabel(Value) plt.ylabel(Frequency) # 子图2密度图归一化 plt.subplot(1, 2, 2) plt.hist(data, bins30, densityTrue, edgecolorblack, alpha0.7, labelHistogram) # 叠加理论正态分布曲线 from scipy.stats import norm x np.linspace(-3, 3, 100) plt.plot(x, norm.pdf(x, 0, 1), r-, linewidth2, labelNormal PDF) plt.title(Density Histogram with PDF) plt.legend() plt.tight_layout() # 自动调整子图间距 plt.show()3.5 箱线图 (Box Plot)箱线图用于展示数据的五数概括最小值、第一四分位数、中位数、第三四分位数、最大值以及异常值。python# 生成多组数据 np.random.seed(42) data1 np.random.normal(0, 1, 100) data2 np.random.normal(2, 1.5, 100) data3 np.random.normal(-1, 0.8, 100) plt.figure(figsize(8, 6)) bp plt.boxplot([data1, data2, data3], labels[Group A, Group B, Group C], patch_artistTrue, # 填充颜色 notchTrue) # 显示凹口 # 设置填充颜色 colors [lightblue, lightgreen, lightpink] for patch, color in zip(bp[boxes], colors): patch.set_facecolor(color) plt.title(Box Plot Comparison) plt.ylabel(Values) plt.grid(axisy, alpha0.3) plt.show()第四章图表样式与高级定制默认的 Matplotlib 图表往往不够美观但通过定制我们可以创建出版级别的图表。4.1 预设样式 (Style)Matplotlib 内置了多种样式一键美化。pythonprint(plt.style.available) # 查看所有可用样式 # [Solarize_Light2, seaborn-v0_8, ggplot, fivethirtyeight, ...] plt.style.use(ggplot) # 使用 ggplot 风格 # 或者使用 seaborn-v0_8-darkgrid, fivethirtyeight 等4.2 颜色与颜色映射 (Colormap)Matplotlib 提供了丰富的颜色映射方案分为三类Sequential: 单色渐变适合连续数据如viridis,plasma,inferno。Diverging: 两极对比适合有正负之分的误差数据如RdBu,coolwarm。Qualitative: 离散颜色适合分类数据如Set1,Paired。python# 绘制一个渐变色散点图 x np.random.rand(500) y np.random.rand(500) z np.random.rand(500) # 颜色映射依据 plt.scatter(x, y, cz, cmapplasma, s50, alpha0.8) plt.colorbar(labelIntensity) plt.show()4.3 文字与注释使用text,annotate可以添加文本和箭头标注。pythonx np.linspace(0, 10, 200) y np.exp(-0.1*x) * np.sin(x) plt.plot(x, y) # 添加普通文本 plt.text(2, 0.6, Damped Oscillation, fontsize12, styleitalic) # 添加带箭头的注释 plt.annotate(Local Maximum, xy(4.7, 0.68), # 箭头指向的点 xytext(6, 0.9), # 文字起始位置 arrowpropsdict(arrowstyle-, colorred, lw1.5), fontsize10, colorred) plt.show()4.4 多子图布局使用subplots可以轻松创建复杂的图形布局。python# 创建 2x2 的子图网格共享 x 轴和 y 轴 fig, axes plt.subplots(2, 2, figsize(10, 8), sharexTrue, shareyTrue) # axes 是一个二维数组索引方式 axes[0,0] x np.linspace(0, 10, 100) axes[0,0].plot(x, np.sin(x)) axes[0,0].set_title(Sin) axes[0,1].plot(x, np.cos(x)) axes[0,1].set_title(Cos) axes[1,0].plot(x, np.tan(x), colorgreen) axes[1,0].set_ylim(-5, 5) # 限制 y 轴范围避免 tan 的无穷大 axes[1,0].set_title(Tan) axes[1,1].scatter(x, np.random.randn(100), alpha0.5) axes[1,1].set_title(Noise) plt.tight_layout() plt.show()更复杂的布局subplot_mosaicMatplotlib 3.3 引入了subplot_mosaic允许用类似 ASCII 艺术的方式定义布局。pythonfig, axd plt.subplot_mosaic([[top, top], [bottom_left, bottom_right]], figsize(8, 5)) axd[top].plot(x, np.sin(x)) axd[bottom_left].hist(np.random.randn(500), bins30) axd[bottom_right].scatter(np.random.randn(200), np.random.randn(200)) plt.show()第五章高级可视化技术5.1 3D 绘图需要导入mplot3d工具包Matplotlib 自带。pythonfrom mpl_toolkits.mplot3d import Axes3D fig plt.figure(figsize(10, 8)) ax fig.add_subplot(111, projection3d) # 生成数据 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)) # 绘制曲面图 surf ax.plot_surface(X, Y, Z, cmapviridis, edgecolornone, alpha0.8) fig.colorbar(surf, shrink0.5, aspect10) ax.set_xlabel(X) ax.set_ylabel(Y) ax.set_zlabel(Z) ax.set_title(3D Surface Plot) plt.show()5.2 动画 (Animation)Matplotlib 的animation模块可以创建动态可视化。pythonimport matplotlib.animation as animation fig, ax plt.subplots() x np.linspace(0, 2*np.pi, 200) line, ax.plot(x, np.sin(x)) # 注意逗号因为 plot 返回一个列表 def animate(i): line.set_ydata(np.sin(x i / 10.0)) # 更新数据 return line, ani animation.FuncAnimation(fig, animate, frames200, interval50, blitTrue) # 保存为 GIF (需要安装 imagemagick) # ani.save(sine_wave.gif, writerimagemagick) plt.show()5.3 图像处理与显示Matplotlib 可以显示 NumPy 数组表示的图像。python# 创建一个随机图像 image np.random.rand(100, 100) plt.imshow(image, cmapgray, interpolationbilinear) plt.colorbar() plt.title(Random Image) plt.show() # 加载真实图像需要 Pillow 或 matplotlib.image import matplotlib.image as mpimg # img mpimg.imread(path/to/image.png) # plt.imshow(img)5.4 极坐标图适合展示方向性或周期性数据。pythonfig plt.figure(figsize(8, 8)) ax fig.add_subplot(111, projectionpolar) # 生成角度和半径数据 theta np.linspace(0, 2*np.pi, 100) r 1 0.5 * np.sin(5 * theta) ax.plot(theta, r, linewidth2) ax.fill(theta, r, alpha0.3) ax.set_title(Polar Plot, vabottom) plt.show()第六章实战案例6.1 案例一金融数据分析股票走势模拟并可视化股票的收盘价、移动平均线和成交量。pythonimport numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import FuncFormatter # 模拟数据 np.random.seed(42) dates np.arange(2023-01, 2023-02, dtypedatetime64[D]) # 1月1日到31日 n len(dates) returns np.random.randn(n) * 0.02 price 100 np.cumsum(returns) # 累计收益模拟价格 volume np.random.randint(1000, 5000, n) # 计算移动平均线 ma5 np.convolve(price, np.ones(5)/5, modevalid) ma5 np.concatenate([np.full(4, np.nan), ma5]) # 对齐长度 # 绘图 fig, (ax1, ax2) plt.subplots(2, 1, figsize(12, 8), sharexTrue, gridspec_kw{height_ratios: [3, 1]}) # 价格子图 ax1.plot(dates, price, labelClose Price, colorblack, linewidth1.5) ax1.plot(dates, ma5, labelMA5, colorred, linestyle--) ax1.set_ylabel(Price ($)) ax1.legend(locupper left) ax1.grid(True, alpha0.3) ax1.set_title(Stock Price and Trading Volume) # 成交量子图 colors [green if p 0 else red for p in np.diff(price, prependprice[0])] ax2.bar(dates, volume, colorcolors, alpha0.6, width0.8) ax2.set_ylabel(Volume) ax2.set_xlabel(Date) ax2.grid(True, axisy, alpha0.3) # 格式化 x 轴日期 plt.xticks(rotation45) plt.tight_layout() plt.show()6.2 案例二机器学习中的决策边界可视化演示如何可视化一个简单分类器的决策边界。pythonfrom sklearn.datasets import make_classification from sklearn.linear_model import LogisticRegression # 生成二分类数据集 X, y make_classification(n_samples200, n_features2, n_redundant0, n_clusters_per_class1, random_state42) # 训练逻辑回归模型 clf LogisticRegression() clf.fit(X, y) # 创建网格以绘制决策边界 x_min, x_max X[:, 0].min() - 1, X[:, 0].max() 1 y_min, y_max X[:, 1].min() - 1, X[:, 1].max() 1 xx, yy np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02)) # 预测网格点的类别 Z clf.predict(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) # 绘图 plt.figure(figsize(10, 6)) plt.contourf(xx, yy, Z, alpha0.3, cmapcoolwarm) # 填充区域 plt.scatter(X[:, 0], X[:, 1], cy, cmapcoolwarm, edgecolorsblack, s50) plt.xlabel(Feature 1) plt.ylabel(Feature 2) plt.title(Logistic Regression Decision Boundary) plt.show()第七章性能优化与最佳实践7.1 避免循环拥抱向量化在处理大量数据点时务必使用 NumPy 的向量化操作而不是 Python 循环。python# 错误示范慢 for i in range(len(x)): plt.plot(x[i], y[i], o) # 正确示范快 plt.scatter(x, y)7.2 管理内存与后端当绘制极大量点如百万级时scatter可能会变得很慢。可以考虑使用plot的linewidth0, marker.代替scatter。对数据进行降采样如使用np.random.choice随机选取子集。如果不需要交互使用非交互式后端如Agg生成图片文件。pythonimport matplotlib matplotlib.use(Agg) # 必须在导入 pyplot 之前设置 import matplotlib.pyplot as plt # ... 绘图代码 ... plt.savefig(output.png)7.3 保存高质量图像pythonplt.savefig(high_quality.png, dpi300, bbox_inchestight, facecolorwhite) # dpi: 分辨率; bbox_inchestight: 自动裁剪空白区域7.4 可复现性设置随机种子以确保结果可复现。pythonnp.random.seed(42)
如何使用 NumPy 和 Matplotlib 进行数据可视化
第一章准备工作与环境搭建在开始数据可视化之前我们需要搭建一个干净、高效的 Python 环境。NumPy 是 Python 科学计算的基石提供了强大的 N 维数组对象Matplotlib 则是 Python 最著名的绘图库能够生成高质量的图表。1.1 环境安装推荐使用 Anaconda 发行版它预装了 NumPy、Matplotlib 以及 Jupyter Notebook 等常用工具。使用 pip 安装bashpip install numpy matplotlib验证安装在 Python 交互式环境或脚本中运行以下代码若无报错则安装成功。pythonimport numpy as np import matplotlib.pyplot as plt print(np.__version__) # 例如1.24.3 print(plt.__version__) # 例如3.7.21.2 核心概念Figure 与 AxesMatplotlib 的绘图逻辑建立在两个核心对象之上Figure (画布)整个图形的最外层容器可以包含一个或多个子图Axes。Axes (坐标系)我们通常所说的“图”。它包含数据区域、坐标轴、刻度、标签等。一个 Figure 可以有多个 Axes。理解这两种对象的区别是摆脱“用plt.plot画简单图”思维迈向复杂布局控制的关键。两种常用的绘图接口pyplot状态机接口 (隐式)类似于 MATLAB 风格通过plt.plot()等命令自动在当前活跃的 Axes 上绘图。适合快速探索。pythonplt.plot(x, y) plt.xlabel(x) plt.ylabel(y) plt.show()面向对象接口 (显式)更推荐尤其在复杂图表中。通过显式调用fig, ax plt.subplots()创建 Figure 和 Axes 对象然后调用ax.plot()等方法。pythonfig, ax plt.subplots() ax.plot(x, y) ax.set_xlabel(x) ax.set_ylabel(y) plt.show()第二章NumPy 在可视化中的角色Matplotlib 本身不计算数据它只负责绘制。NumPy 则负责生成、处理和转换数据。两者结合使用可以高效地探索数据模式。2.1 生成数据源NumPy 提供了丰富的函数来生成测试数据这对于学习绘图非常方便。pythonimport numpy as np import matplotlib.pyplot as plt # 1. 线性空间生成 x 轴数据 x np.linspace(0, 10, 100) # 在 [0, 10] 区间生成 100 个均匀分布的点 y1 np.sin(x) # 正弦函数 y2 np.cos(x) # 余弦函数 # 2. 随机数据模拟真实场景 data np.random.normal(loc0, scale1, size1000) # 正态分布数据 noise np.random.rand(50) * 2 - 1 # 均匀分布噪声 [-1, 1]2.2 向量化计算与绘图NumPy 的核心优势是向量化计算。它允许我们对整个数组进行操作而无需编写显式循环。这极大地提高了代码效率和可读性。python# 非向量化方式慢不推荐 x [i for i in range(10)] y [] for xi in x: y.append(xi**2) # 向量化方式快推荐 x np.arange(10) y x ** 2 # 对数组中每个元素求平方 # 绘图 plt.plot(x, y) plt.show()2.3 处理不规则数据在实际应用中数据往往是不完整的。NumPy 的np.nan(Not a Number) 配合 Matplotlib 可以优雅地处理缺失值。pythonx np.linspace(0, 10, 100) y np.sin(x) # 人为制造一段缺失数据 y[20:40] np.nan plt.plot(x, y, labelsin(x) with gap) plt.legend() plt.show() # Matplotlib 会自动跳过 np.nan 对应的点断开线条第三章基础图表绘制本章将介绍最常用的几种图表类型并解释其核心参数。3.1 折线图 (Line Plot)折线图用于显示数据随时间或有序变量变化的趋势。pythonx np.linspace(0, 2 * np.pi, 50) y_sin np.sin(x) y_cos np.cos(x) plt.figure(figsize(10, 6)) # 设置画布大小英寸 plt.plot(x, y_sin, colorblue, # 颜色 linestyle--, # 线型-, --, -., : linewidth2, # 线宽 markero, # 数据点标记o, ^, s, D, x 等 markersize4, # 标记大小 labelsin(x)) # 图例标签 plt.plot(x, y_cos, colorred, linestyle-, labelcos(x)) plt.xlabel(x (radians)) plt.ylabel(Amplitude) plt.title(Sine and Cosine Waves) plt.legend(locupper right) # 图例位置 plt.grid(True, alpha0.3) # 显示网格透明度0.3 plt.show()3.2 散点图 (Scatter Plot)散点图用于观察两个变量之间的相关性、分布以及异常值。python# 生成 200 个随机点 n 200 x np.random.randn(n) y np.random.randn(n) colors np.random.rand(n) # 随机颜色值 sizes np.random.randint(20, 200, n) # 随机点大小 plt.figure(figsize(8, 6)) sc plt.scatter(x, y, ccolors, # 颜色映射 ssizes, # 点大小 alpha0.6, # 透明度 cmapviridis) # 颜色映射方案 plt.colorbar(sc) # 显示颜色条 plt.xlabel(X) plt.ylabel(Y) plt.title(Scatter Plot with Color and Size Mapping) plt.show()3.3 柱状图 (Bar Plot)柱状图用于比较不同类别的数值。pythoncategories [A, B, C, D, E] values np.random.randint(10, 100, size5) plt.figure(figsize(8, 5)) bars plt.bar(categories, values, color[#FF9999, #66B2FF, #99FF99, #FFCC99, #FF99CC], edgecolorblack, linewidth1) # 在柱子上方添加数值标签 for bar in bars: height bar.get_height() plt.text(bar.get_x() bar.get_width()/2., height 1, f{height}, hacenter, vabottom) plt.xlabel(Category) plt.ylabel(Value) plt.title(Bar Chart Example) plt.show()水平柱状图pythonplt.barh(categories, values) # 使用 barh3.4 直方图 (Histogram)直方图用于展示连续变量的分布情况。python# 生成符合正态分布的数据 data np.random.randn(1000) plt.figure(figsize(10, 5)) # 子图1默认直方图 plt.subplot(1, 2, 1) # 1行2列第1个图 plt.hist(data, bins30, edgecolorblack, alpha0.7) plt.title(Histogram (bins30)) plt.xlabel(Value) plt.ylabel(Frequency) # 子图2密度图归一化 plt.subplot(1, 2, 2) plt.hist(data, bins30, densityTrue, edgecolorblack, alpha0.7, labelHistogram) # 叠加理论正态分布曲线 from scipy.stats import norm x np.linspace(-3, 3, 100) plt.plot(x, norm.pdf(x, 0, 1), r-, linewidth2, labelNormal PDF) plt.title(Density Histogram with PDF) plt.legend() plt.tight_layout() # 自动调整子图间距 plt.show()3.5 箱线图 (Box Plot)箱线图用于展示数据的五数概括最小值、第一四分位数、中位数、第三四分位数、最大值以及异常值。python# 生成多组数据 np.random.seed(42) data1 np.random.normal(0, 1, 100) data2 np.random.normal(2, 1.5, 100) data3 np.random.normal(-1, 0.8, 100) plt.figure(figsize(8, 6)) bp plt.boxplot([data1, data2, data3], labels[Group A, Group B, Group C], patch_artistTrue, # 填充颜色 notchTrue) # 显示凹口 # 设置填充颜色 colors [lightblue, lightgreen, lightpink] for patch, color in zip(bp[boxes], colors): patch.set_facecolor(color) plt.title(Box Plot Comparison) plt.ylabel(Values) plt.grid(axisy, alpha0.3) plt.show()第四章图表样式与高级定制默认的 Matplotlib 图表往往不够美观但通过定制我们可以创建出版级别的图表。4.1 预设样式 (Style)Matplotlib 内置了多种样式一键美化。pythonprint(plt.style.available) # 查看所有可用样式 # [Solarize_Light2, seaborn-v0_8, ggplot, fivethirtyeight, ...] plt.style.use(ggplot) # 使用 ggplot 风格 # 或者使用 seaborn-v0_8-darkgrid, fivethirtyeight 等4.2 颜色与颜色映射 (Colormap)Matplotlib 提供了丰富的颜色映射方案分为三类Sequential: 单色渐变适合连续数据如viridis,plasma,inferno。Diverging: 两极对比适合有正负之分的误差数据如RdBu,coolwarm。Qualitative: 离散颜色适合分类数据如Set1,Paired。python# 绘制一个渐变色散点图 x np.random.rand(500) y np.random.rand(500) z np.random.rand(500) # 颜色映射依据 plt.scatter(x, y, cz, cmapplasma, s50, alpha0.8) plt.colorbar(labelIntensity) plt.show()4.3 文字与注释使用text,annotate可以添加文本和箭头标注。pythonx np.linspace(0, 10, 200) y np.exp(-0.1*x) * np.sin(x) plt.plot(x, y) # 添加普通文本 plt.text(2, 0.6, Damped Oscillation, fontsize12, styleitalic) # 添加带箭头的注释 plt.annotate(Local Maximum, xy(4.7, 0.68), # 箭头指向的点 xytext(6, 0.9), # 文字起始位置 arrowpropsdict(arrowstyle-, colorred, lw1.5), fontsize10, colorred) plt.show()4.4 多子图布局使用subplots可以轻松创建复杂的图形布局。python# 创建 2x2 的子图网格共享 x 轴和 y 轴 fig, axes plt.subplots(2, 2, figsize(10, 8), sharexTrue, shareyTrue) # axes 是一个二维数组索引方式 axes[0,0] x np.linspace(0, 10, 100) axes[0,0].plot(x, np.sin(x)) axes[0,0].set_title(Sin) axes[0,1].plot(x, np.cos(x)) axes[0,1].set_title(Cos) axes[1,0].plot(x, np.tan(x), colorgreen) axes[1,0].set_ylim(-5, 5) # 限制 y 轴范围避免 tan 的无穷大 axes[1,0].set_title(Tan) axes[1,1].scatter(x, np.random.randn(100), alpha0.5) axes[1,1].set_title(Noise) plt.tight_layout() plt.show()更复杂的布局subplot_mosaicMatplotlib 3.3 引入了subplot_mosaic允许用类似 ASCII 艺术的方式定义布局。pythonfig, axd plt.subplot_mosaic([[top, top], [bottom_left, bottom_right]], figsize(8, 5)) axd[top].plot(x, np.sin(x)) axd[bottom_left].hist(np.random.randn(500), bins30) axd[bottom_right].scatter(np.random.randn(200), np.random.randn(200)) plt.show()第五章高级可视化技术5.1 3D 绘图需要导入mplot3d工具包Matplotlib 自带。pythonfrom mpl_toolkits.mplot3d import Axes3D fig plt.figure(figsize(10, 8)) ax fig.add_subplot(111, projection3d) # 生成数据 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)) # 绘制曲面图 surf ax.plot_surface(X, Y, Z, cmapviridis, edgecolornone, alpha0.8) fig.colorbar(surf, shrink0.5, aspect10) ax.set_xlabel(X) ax.set_ylabel(Y) ax.set_zlabel(Z) ax.set_title(3D Surface Plot) plt.show()5.2 动画 (Animation)Matplotlib 的animation模块可以创建动态可视化。pythonimport matplotlib.animation as animation fig, ax plt.subplots() x np.linspace(0, 2*np.pi, 200) line, ax.plot(x, np.sin(x)) # 注意逗号因为 plot 返回一个列表 def animate(i): line.set_ydata(np.sin(x i / 10.0)) # 更新数据 return line, ani animation.FuncAnimation(fig, animate, frames200, interval50, blitTrue) # 保存为 GIF (需要安装 imagemagick) # ani.save(sine_wave.gif, writerimagemagick) plt.show()5.3 图像处理与显示Matplotlib 可以显示 NumPy 数组表示的图像。python# 创建一个随机图像 image np.random.rand(100, 100) plt.imshow(image, cmapgray, interpolationbilinear) plt.colorbar() plt.title(Random Image) plt.show() # 加载真实图像需要 Pillow 或 matplotlib.image import matplotlib.image as mpimg # img mpimg.imread(path/to/image.png) # plt.imshow(img)5.4 极坐标图适合展示方向性或周期性数据。pythonfig plt.figure(figsize(8, 8)) ax fig.add_subplot(111, projectionpolar) # 生成角度和半径数据 theta np.linspace(0, 2*np.pi, 100) r 1 0.5 * np.sin(5 * theta) ax.plot(theta, r, linewidth2) ax.fill(theta, r, alpha0.3) ax.set_title(Polar Plot, vabottom) plt.show()第六章实战案例6.1 案例一金融数据分析股票走势模拟并可视化股票的收盘价、移动平均线和成交量。pythonimport numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import FuncFormatter # 模拟数据 np.random.seed(42) dates np.arange(2023-01, 2023-02, dtypedatetime64[D]) # 1月1日到31日 n len(dates) returns np.random.randn(n) * 0.02 price 100 np.cumsum(returns) # 累计收益模拟价格 volume np.random.randint(1000, 5000, n) # 计算移动平均线 ma5 np.convolve(price, np.ones(5)/5, modevalid) ma5 np.concatenate([np.full(4, np.nan), ma5]) # 对齐长度 # 绘图 fig, (ax1, ax2) plt.subplots(2, 1, figsize(12, 8), sharexTrue, gridspec_kw{height_ratios: [3, 1]}) # 价格子图 ax1.plot(dates, price, labelClose Price, colorblack, linewidth1.5) ax1.plot(dates, ma5, labelMA5, colorred, linestyle--) ax1.set_ylabel(Price ($)) ax1.legend(locupper left) ax1.grid(True, alpha0.3) ax1.set_title(Stock Price and Trading Volume) # 成交量子图 colors [green if p 0 else red for p in np.diff(price, prependprice[0])] ax2.bar(dates, volume, colorcolors, alpha0.6, width0.8) ax2.set_ylabel(Volume) ax2.set_xlabel(Date) ax2.grid(True, axisy, alpha0.3) # 格式化 x 轴日期 plt.xticks(rotation45) plt.tight_layout() plt.show()6.2 案例二机器学习中的决策边界可视化演示如何可视化一个简单分类器的决策边界。pythonfrom sklearn.datasets import make_classification from sklearn.linear_model import LogisticRegression # 生成二分类数据集 X, y make_classification(n_samples200, n_features2, n_redundant0, n_clusters_per_class1, random_state42) # 训练逻辑回归模型 clf LogisticRegression() clf.fit(X, y) # 创建网格以绘制决策边界 x_min, x_max X[:, 0].min() - 1, X[:, 0].max() 1 y_min, y_max X[:, 1].min() - 1, X[:, 1].max() 1 xx, yy np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02)) # 预测网格点的类别 Z clf.predict(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) # 绘图 plt.figure(figsize(10, 6)) plt.contourf(xx, yy, Z, alpha0.3, cmapcoolwarm) # 填充区域 plt.scatter(X[:, 0], X[:, 1], cy, cmapcoolwarm, edgecolorsblack, s50) plt.xlabel(Feature 1) plt.ylabel(Feature 2) plt.title(Logistic Regression Decision Boundary) plt.show()第七章性能优化与最佳实践7.1 避免循环拥抱向量化在处理大量数据点时务必使用 NumPy 的向量化操作而不是 Python 循环。python# 错误示范慢 for i in range(len(x)): plt.plot(x[i], y[i], o) # 正确示范快 plt.scatter(x, y)7.2 管理内存与后端当绘制极大量点如百万级时scatter可能会变得很慢。可以考虑使用plot的linewidth0, marker.代替scatter。对数据进行降采样如使用np.random.choice随机选取子集。如果不需要交互使用非交互式后端如Agg生成图片文件。pythonimport matplotlib matplotlib.use(Agg) # 必须在导入 pyplot 之前设置 import matplotlib.pyplot as plt # ... 绘图代码 ... plt.savefig(output.png)7.3 保存高质量图像pythonplt.savefig(high_quality.png, dpi300, bbox_inchestight, facecolorwhite) # dpi: 分辨率; bbox_inchestight: 自动裁剪空白区域7.4 可复现性设置随机种子以确保结果可复现。pythonnp.random.seed(42)