目录7
文章/Matplotlib/第 26 章
风羽图
Matplotlib · 第 26 / 43 章
barbs() —— 风羽图
风羽(wind barb)是气象学的标准符号:一根“杆” + 杆尾的旗/羽表示风速,杆的指向表示风的来向。一个符号同时编码风速和风向,比箭头省地方得多。
读法(记住这三条就够):
| 杆尾的符号 | 代表风速增量(默认) |
|---|---|
| 半条羽(短斜线) | 5 |
| 一条完整羽(长斜线) | 10 |
| 一个实心三角(旗) | 50 |
例:1 个旗 + 1 条全羽 + 1 条半羽 = 50 + 10 + 5 = 65。
Axes.barbs(
X, Y, U, V, # 位置 + 分量
C=None, # 上色依据
length=7, # 杆长(点,pt)
pivot="tip", # ★ 锚点:tip / middle
barbcolor=None, # 杆和羽的颜色
flagcolor=None, # 旗的颜色(不设则跟随 barbcolor)
sizes=None, # dict:spacing / height / width / emptybarb
barb_increments=None, # ★ dict:half / full / flag 各代表多少
rounding=True, # 是否把 U/V 四舍五入到整数
flip_barb=False, # 羽画在杆的另一侧
fill_empty=False, # 风速低于半羽时画空圈
linewidth=0.5,
data=None,
**kwargs
)| 参数 | 一句话 | 默认值的影响 |
|---|---|---|
U / V |
风的两个分量 | 单位随意,只要和 barb_increments 配套 |
barb_increments |
各级代表多少 | {half:5, full:10, flag:50}(节) |
sizes |
杆几何 | spacing/height/width/emptybarb |
pivot |
锚点 | 'tip':格点是箭尖(气象惯例) |
length |
杆长 | 7 pt |
flip_barb |
羽在哪侧 | False(北半球惯例) |
rounding |
是否取整 | True,与整数值的 increments 配套 |
最小示例
import numpy as np
import matplotlib.pyplot as plt
xb = np.linspace(-2, 2, 9)
yb = np.linspace(-2, 2, 9)
Xb, Yb = np.meshgrid(xb, yb)
Ub = -Yb * 8 # 风速量级 ~20,才会出现旗
Vb = Xb * 8
fig, ax = plt.subplots()
ax.barbs(Xb, Yb, Ub, Vb, length=5)
plt.show()
U、V 的单位要和 barb_increments 一致。默认 increments 是「节」,所以先用真实风速(节)画,再考虑换算——把 m/s 的 8 直接喂进去,只会得到一个半羽。
barb_increments:改每一级代表多少
ax.barbs(Xb, Yb, Ub, Vb, barb_increments=dict(half=2.5, full=5, flag=25))数据单位是 m/s 时常用这套(半羽 2.5 m/s、全羽 5 m/s、旗 25 m/s)。三个键必须同时给——只给 half 会让另外两个回到默认值,符号系统立刻自相矛盾。
sizes:杆和羽的几何
ax.barbs(Xb, Yb, Ub, Vb, length=6, linewidth=1.2,
sizes=dict(spacing=0.22, height=0.45, width=0.28))sizes 是个字典,键是 spacing(羽的间距)、height(羽的高度)、width(杆宽)、emptybarb(空圈半径)。全部是 length 的比例,所以改 length 会等比缩放整套符号。
pivot / flip_barb:符号挂在哪、朝哪边
ax.barbs(Xb, Yb, Ub, Vb, pivot="middle") # 格点是符号中心
ax.barbs(Xb, Yb, Ub, Vb, flip_barb=True) # 羽画到杆的另一侧(南半球惯例)pivot 默认 'tip':格点是风来的方向那一端,这是气象图的惯例(符号从站点向外指)。画在格点正中的散点式布局要改成 'middle'。
flip_barb 是南北半球约定问题。默认 False 对应北半球(羽在杆的左侧);南半球气象图要设 True。
返回对象
bb = ax.barbs(Xb, Yb, Ub, Vb)
print(type(bb).__name__)
# 输出: Barbs
print(bb.barb_increments)
# 输出: {} ← 空字典 = 用内置默认 5/10/50,不是记录实际生效值
# 显式传过才会回显:{'half': 2.5, 'full': 5, 'flag': 25}
bb.set_UVC(Ub * 2, Vb * 2) # 换数据
bb.set_array(np.hypot(Ub, Vb)) # 换上色数组
bb.set_clim(0, 30)
plt.show()Barbs 和 Quiver 是兄弟类(都继承自 Collection),同样有 set_UVC() 可以原地更新——做风场时间序列动画时这就是关键。
注意事项
- 读法容易记反:半羽 5、全羽 10、旗 50,是杆尾符号的累加,不是杆长。
U、V的单位必须与barb_increments配套;默认按“节”。- 三个
barb_increments键要一起给,只改一个会让符号系统不自洽。 pivot默认'tip'(气象惯例),散点布局要改'middle'。flip_barb是半球约定,国内图用默认False。- 风速太小时符号退化成一根空杆,必要时
fill_empty=True画空圈表示“有风但很弱”。 - 风羽只适合稀疏取样(10×10 以内),密了完全读不出来——密场请用
streamplot。
综合示例:三套增量 / 锚点对比 / 稀疏风场
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei", "DejaVu Sans"]
plt.rcParams["axes.unicode_minus"] = False
xb = np.linspace(-2, 2, 9)
yb = np.linspace(-2, 2, 9)
Xb, Yb = np.meshgrid(xb, yb)
Ub = -Yb * 10 + 4 # 涡 + 均匀西风
Vb = Xb * 10
fig, axes = plt.subplots(1, 3, figsize=(15, 4.6))
# ---- (a) 默认增量(节) ----
axes[0].barbs(Xb, Yb, Ub, Vb, length=5)
axes[0].set_title("(a) 默认 half=5 / full=10 / flag=50")
# ---- (b) m/s 增量:同一份数据,符号完全不同 ----
axes[1].barbs(Xb, Yb, Ub, Vb, length=5,
barb_increments=dict(half=2.5, full=5, flag=25))
axes[1].set_title("(b) half=2.5 / full=5 / flag=25")
# ---- (c) 稀疏 + 锚点居中 + 自定义配色 ----
axes[2].barbs(Xb[::2, ::2], Yb[::2, ::2], Ub[::2, ::2], Vb[::2, ::2],
length=7, pivot="middle", linewidth=1.1,
barbcolor="#1f4e79", flagcolor="#C44E52",
sizes=dict(spacing=0.2, height=0.45, width=0.26))
axes[2].set_title("(c) 稀疏取样 + pivot='middle' + 双色")
for ax in axes:
ax.set_aspect("equal")
ax.set_xlim(-2.2, 2.2)
ax.set_ylim(-2.2, 2.2)
plt.tight_layout()
plt.show()(a) 和 (b) 用的是同一份 U、V,只换了 barb_increments,符号密度就完全不同——这就是为什么这个参数必须和数据的单位绑定。图例上(或图注里)一定要标清楚“半羽 = 5 节”还是“半羽 = 2.5 m/s”,否则图是没有办法读的。