本系列文章配套代码获取有以下两种途径:
-
通过百度网盘获取:
链接:https://pan.baidu.com/s/1jG-rGG4QMuZu0t0kEEl7SA?pwd=mnsj
提取码:mnsj
-
前往GitHub获取:
https://github.com/returu/Data_Visualization
函数语法:
plt.streamplot(x, y, u, v, density=1, linewidth=None,
color=None, cmap=None, norm=None, arrowsize=1,
arrowstyle='-|>', minlength=0.1, transform=None,
zorder=None, start_points=None, maxlength=4.0,
integration_direction='both',
broken_streamlines=True, *, data=None)
-
核心参数:
-
x, y:数组类型定义向量场的坐标。可以是 1D 数组(将被网格化为 2D)或 2D 数组(必须与 u 和 v 的形状匹配)。如果是 1D 数组,x 的长度对应网格的列数,y 的长度对应网格的行数。 -
u, v:2D 数组,表示向量场的分量,u 对应 x 方向的速度分量,v 对应 y 方向的速度分量。必须与 x 和 y 的网格形状相匹配。
-
流线控制参数:
-
density:浮点数或元组,默认值为 1,控制流线的密度,值越大,流线越多。若为元组形式 (dx, dy),则分别控制 x 和 y 方向的密度。 -
linewidth:控制流线宽度,可传入固定值或数组,若为数组,其形状必须与 u 和 v 相同,用于根据数据值改变线宽。 -
color:颜色或数组,控制线的颜色。若为数组,其形状必须与 u 和 v 相同,用于根据数据值改变颜色。 -
cmap:当 color 为数组时使用的颜色映射。 -
norm:用于将数据值标准化到 [0,1] 范围,配合 colormap 使用。
-
arrowsize:流线中箭头的大小,默认值为 1,值越大箭头越明显。
-
arrowstyle:箭头样式,可选项包括:‘-‘、’->’、'<-‘、’-[‘、’]-‘ 等。
-
minlength:流线的最小长度,以轴坐标为单位,默认值为 0.1。
-
start_points:手动指定流线的起始点,形状为 (n, 2) 的数组,每行表示一个起始点 (x, y)。
-
maxlength:流线的最大长度,以平均步长的倍数表示,默认值为 4.0。
-
transform:应用于所有流线的变换。
-
其他参数:
-
zorder:控制绘图元素的堆叠顺序,值越大越靠上。
-
integration_direction:控制流线的积分方向,可选项包括:‘both’(同时向前后两个方向积分)、‘forward’(只向前积分)、‘backward’(只向后积分)。
-
broken_streamlines:是否允许流线在遇到NaN或无限值时断开, 默认为True。
-
data:可索引对象,若提供,参数x, y, u, v, start_points可接受字符串s,解释为data[s]。
通过调整这些参数,可以灵活控制流线图的视觉效果。
# 创建网格
x = np.linspace(-2, 2, 100)
y = np.linspace(-2, 2, 100)
X, Y = np.meshgrid(x, y)
# 创建矢量场(一个简单的涡旋场)
U = -Y
V = X
# 计算流速大小
speed = np.sqrt(U**2 + V**2)
# 创建图形
plt.figure(figsize=(8, 6))
# 绘制流线图
streamplot = plt.streamplot(X, Y, # 网格点的x、y坐标
U, V, # 对应网格点的x、y方向速度分量
density=(2, 1), # 流线密度(值越大,流线越多越密集)
color=speed, # 根据流速着色
cmap='viridis', # 颜色映射
linewidth=2*speed, # 根据流速调整线宽
arrowsize=2, # 箭头大小
arrowstyle='-|>' # 箭头样式
)
# 添加颜色条
plt.colorbar(streamplot.lines, label='流速大小')
plt.title('涡旋流场可视化')
plt.xlabel('X轴')
plt.ylabel('Y轴')
plt.show()
可视化结果如下图所示:

使用示例:
-
示例 1:利用返回值修改流线图样式
streamplot()函数返回一个StreamplotSet对象,包含两个重要属性:
-
lines:表示流线的LineCollection对象;
-
arrows:表示箭头的PatchCollection对象。
通过修改这些对象的属性,我们可以实现更精细的样式定制。
import matplotlib.pyplot as plt
import numpy as np
# 生成示例数据 - 漩涡场
x = np.linspace(-3, 3, 30)
y = np.linspace(-3, 3, 30)
X, Y = np.meshgrid(x, y)
# 计算向量场(漩涡效果)
u = -Y
v = X
speed = np.sqrt(u**2 + v**2) # 计算速度大小用于条件判断
# 创建包含三个子图的画布
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 6))
fig.suptitle('流线图样式修改对比', fontsize=16, fontweight='bold')
# --------------------------
# 1. 原始流线图
# --------------------------
stream1 = ax1.streamplot(
X, Y, u, v,
density=1.2,
arrowsize=1.5,
color='black'
)
ax1.set_title('1. 原始图', fontsize=14)
ax1.set_xlabel('X轴')
ax1.set_ylabel('Y轴')
ax1.set_aspect('equal')
# --------------------------
# 2. 整体修改后的流线图
# --------------------------
stream2 = ax2.streamplot(
X, Y, u, v,
density=1.2,
arrowsize=1.5
)
# 修改所有流线属性
stream2.lines.set_color('teal')
stream2.lines.set_linewidth(1.5)
stream2.lines.set_alpha(0.8)
# 修改所有箭头属性
stream2.arrows.set_color('crimson')
stream2.arrows.set_alpha(0.9)
stream2.arrows.set_linewidth(1.2)
stream2.arrows.set_zorder(3) # 确保箭头在流线上方
ax2.set_title('2. 整体修改后', fontsize=14)
ax2.set_xlabel('X轴')
ax2.set_ylabel('Y轴')
ax2.set_aspect('equal')
# --------------------------
# 3. 基于条件修改特定流线
# --------------------------
stream3 = ax3.streamplot(
X, Y, u, v,
density=1.2,
arrowsize=1.5
)
# 根据速度大小设置不同流线的颜色和宽度
# 获取流线的数量(通过路径数量判断)
num_paths = len(stream3.lines.get_paths())
# 存储每个流线的颜色和宽度
colors = []
linewidths = []
# 为每个流线设置属性(基于对应位置的速度)
for i in range(num_paths):
# 获取当前流线的路径对象
path = stream3.lines.get_paths()[i]
# 计算路径中点的索引(取路径顶点的中间位置)
mid_point_idx = int(len(path.vertices)/2)
# 获取中点的坐标(x_mid, y_mid)
x_mid, y_mid = path.vertices[mid_point_idx]
# 找到与中点最接近的速度数据点索引
# 计算x轴上与x_mid最接近的点的索引
x_idx = np.argmin(np.abs(x - x_mid))
# 计算y轴上与y_mid最接近的点的索引
y_idx = np.argmin(np.abs(y - y_mid))
# 获取该位置的速度值
speed_val = speed[y_idx, x_idx]
# 根据速度设置颜色和线宽
if speed_val > 2.0:
colors.append('red')
linewidths.append(2.5)
elif speed_val > 1.0:
colors.append('orange')
linewidths.append(1.8)
else:
colors.append('blue')
linewidths.append(1.0)
# 应用条件样式
stream3.lines.set_color(colors)
stream3.lines.set_linewidth(linewidths)
ax3.set_title('3. 基于速度的条件修改', fontsize=14)
ax3.set_xlabel('X轴')
ax3.set_ylabel('Y轴')
ax3.set_aspect('equal')
# 添加颜色说明图例
from matplotlib.lines import Line2D
legend_elements = [
Line2D([0], [0], color='blue', lw=1.0, label='低速 (<=1.0)'),
Line2D([0], [0], color='orange', lw=1.8, label='中速 (1.0-2.0)'),
Line2D([0], [0], color='red', lw=2.5, label='高速 (>2.0)')
]
ax3.legend(handles=legend_elements, loc='upper right', fontsize=10)
plt.tight_layout()
plt.subplots_adjust(top=0.85)
plt.show()
可视化结果如下图所示:

-
示例 2:与其他图表结合,增加视觉效果
将流线图与其他图表结合使用,可以增强数据可视化的层次感和信息量。
例如,通过叠加散点图、等高线图来增强数据可视化效果:
from matplotlib.colors import LinearSegmentedColormap
# 生成基础数据 - 模拟流体流动场景
x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
X, Y = np.meshgrid(x, y)
# 定义向量场(包含两个漩涡和一个中心障碍物)
u = -1 - X**2 + Y
v = 1 + X - Y**2
# 计算速度大小(用于颜色映射)
speed = np.sqrt(u**2 + v**2)
# 创建自定义颜色映射
colors = [(0.8, 0.9, 1), (0, 0.4, 0.8)] # 浅蓝色到深蓝色
cmap = LinearSegmentedColormap.from_list('custom_cmap', colors, N=100)
# 创建2x2的子图布局
fig, axes = plt.subplots(1, 2, figsize=(10, 8))
# --------------------------
# 1. 流线图 + 散点图(标记关键点)
# --------------------------
ax1 = axes[0]
# 绘制流线图
stream1 = ax1.streamplot(X, Y, u, v, density=1.2, color=speed, cmap=cmap, linewidth=1)
# 添加颜色条
cbar1 = fig.colorbar(stream1.lines, ax=ax1, shrink=0.5)
cbar1.set_label('速度大小')
# 标记特殊点(停滞点和最大速度点)
stagnation_points = np.array([[0, 1], [-2, -1]]) # 停滞点坐标
max_speed_idx = np.unravel_index(np.argmax(speed), speed.shape)
max_speed_point = np.array([X[max_speed_idx], Y[max_speed_idx]])
# 绘制散点
ax1.scatter(stagnation_points[:, 0], stagnation_points[:, 1],
c='red', s=100, marker='x', label='停滞点')
ax1.set_title('1. 流线图 + 散点图', fontsize=14)
ax1.set_xlabel('X轴')
ax1.set_ylabel('Y轴')
ax1.legend()
ax1.set_aspect('equal')
# --------------------------
# 2. 流线图 + 等高线图(叠加标量场)
# --------------------------
ax2 = axes[1]
# 计算压力场(模拟数据,与速度成反比)
pressure = 100 - 0.5 * speed**2
# 绘制填充等高线图表示压力场
contour = ax2.contourf(X, Y, pressure, 20, cmap='viridis', alpha=0.5)
cbar2 = fig.colorbar(contour, ax=ax2, shrink=0.5)
cbar2.set_label('压力值')
# 在等高线图上叠加流线图
stream2 = ax2.streamplot(X, Y, u, v, density=1.2, color='black', linewidth=0.8, arrowsize=1)
ax2.set_title('2. 流线图 + 等高线图', fontsize=14)
ax2.set_xlabel('X轴')
ax2.set_ylabel('Y轴')
ax2.set_aspect('equal')
plt.show()
可视化结果如下图所示:

更多内容可以前往官网查看:
https://matplotlib.org/stable/


本篇文章来源于微信公众号: 码农设计师