sacpy的简单用法
1573 字
8 分钟
sacpy的简单用法
sacpy 使用方法指南
本文档整理自
相关代码目录中涉及 sacpy 的 Python 脚本,汇总了 sacpy 库在气象数据分析中的核心用法,包括距平计算、线性回归、EOF 分析及地图绘图增强。
一、安装
pip install sacpy二、距平计算 — scp.get_anom
2.1 基本用法
import sacpy as scp
ssta = scp.get_anom(sst, method=1)2.2 参数说明
| 参数 | 说明 |
|---|---|
sst | xarray DataArray,维度 (time, lat, lon) |
method=1 | 方法1:逐月去气候态(减去各月多年平均),即去季节循环 |
2.3 完整示例(来源:ENSO_regression_sacpy.py<16>16>)
import xarray as xrimport sacpy as scp
ds = xr.open_dataset('sst.mnmean.nc')sst = ds['sst'].sel(time=slice('1950','2020'))sst = scp.get_anom(sst, method=1)2.4 多变量批量去距平(来源:Nino12_regression_sst_uv_sacpy.py<24-26>24-26>)
sst = scp.get_anom(sst, method=1)uwnd = scp.get_anom(uwnd, method=1)vwnd = scp.get_anom(vwnd, method=1)三、线性回归 — scp.LinReg
3.1 基本用法
LinReg = scp.LinReg(index, field)slope = LinReg.slope # 回归系数场 (lat, lon)p_value = LinReg.p_value # p 值场 (lat, lon)3.2 参数说明
| 参数 | 说明 |
|---|---|
index | 一维时间序列(如 Nino34 指数),形状 (time,) |
field | 二维或三维场(如 SST),形状 (time, lat, lon) |
3.3 返回值属性
| 属性 | 说明 |
|---|---|
.slope | 回归系数场(斜率),形状与 field 的空间维度一致 |
.p_value | p 值场,形状与 slope 一致 |
3.4 完整示例(来源:ENSO_regression_sacpy.py<18-21>18-21>)
# 计算 Nino34 指数nino34 = sst.loc[:, 5:-5, 190:240].mean(dim=['lat', 'lon'])
# 线性回归:将 SST 场回归到 Nino34 指数LinReg = scp.LinReg(nino34, sst)slope = LinReg.slopep_value = LinReg.p_value3.5 多变量逐个回归(来源:Nino12_regression_sst_uv_sacpy.py<28-35>28-35>)
nino12 = sst.loc[:, 10:0, 270:280].mean(dim=['lat', 'lon'])
map_sst = scp.LinReg(nino12, sst)map_uwnd = scp.LinReg(nino12, uwnd)map_vwnd = scp.LinReg(nino12, vwnd)3.6 显著性过滤
import numpy as np
# 将不显著的格点设为 NaN(绘图时不显示)sst_tmp = np.where(map_sst.p_value >= 0.05, np.nan, map_sst.slope)uwnd_tmp = np.where(map_uwnd.p_value >= 0.10, np.nan, map_uwnd.slope)vwnd_tmp = np.where(map_vwnd.p_value >= 0.10, np.nan, map_vwnd.slope)| 参数 | 说明 |
|---|---|
condition | 条件表达式,如 p_value >= 0.05 |
np.nan | 满足条件时的替换值 |
map.slope | 不满足条件时的原值 |
四、EOF 分析 — scp.EOF
4.1 基本用法
eof = scp.EOF(ssta) # 初始化eof.solve() # 求解pc = eof.get_pc(npt=3) # 获取 PC(时间序列)pt = eof.get_pt(npt=3) # 获取空间模态pcvar = eof.get_varperc(npt=3) * 100 # 解释方差百分比(%)4.2 方法说明
| 方法 | 参数 | 说明 |
|---|---|---|
scp.EOF(data) | data | 输入距平场 (time, lat, lon) |
.solve() | — | 执行 EOF 分解 |
.get_pc(npt) | npt | 返回前 npt 个主成分,形状 (npt, time) |
.get_pt(npt) | npt | 返回前 npt 个空间模态,形状 (npt, lat, lon) |
.get_varperc(npt) | npt | 返回前 npt 个模态的方差占比(小数,需 ×100 得百分比) |
4.3 完整示例(来源:EOF_sst_sacpy.py<16-25>16-25>)
import xarray as xrimport sacpy as scp
ds = xr.open_dataset('sst.mnmean.nc')sst = ds['sst'].sel(time=slice('1950','2020')).loc[:, 30:-30, 90:300]
# 计算距平ssta = scp.get_anom(sst, method=1)
# EOF 计算eof = scp.EOF(ssta)eof.solve()
# 获取 PC 和空间模态pc = -eof.get_pc(npt=3) # 取负号可翻转符号,视需求而定pt = -eof.get_pt(npt=3)
# 获取解释方差百分比pcvar = eof.get_varperc(npt=3) * 100注意:PC 和 pattern 的符号可同时取反而不会改变物理意义,这与求解器内部约定有关。
4.4 绘制 EOF 模态与 PC(来源:EOF_sst_sacpy.py<31-55>31-55>)
import matplotlib.pyplot as pltimport cartopy.crs as ccrsimport sacpy.Map
fig = plt.figure(figsize=[9, 10])for i in range(3): # EOF 空间模态 ax = fig.add_subplot(3, 2, 2*i+1, projection=ccrs.PlateCarree(central_longitude=180)) m1 = ax.scontourf(lon, lat, pt[i, :, :], cmap='RdBu_r', levels=np.linspace(-0.75, 0.75, 15), extend="both") ax.scontour(m1, colors="black") ax.init_map(smally=2.5) ax.set_title("EOF-{} ({:.2f}%)".format(i+1, pcvar[i]))
# PC 时间序列 ax = fig.add_subplot(3, 2, 2*i+2) ax.plot(sst.time, pc[i]) ax.set_title("PC-{}".format(i+1))
# colorbarcb_ax = fig.add_axes([0.1, 0.06, 0.4, 0.02])fig.colorbar(m1, cax=cb_ax, orientation="horizontal")五、sacpy.Map 绘图增强
sacpy.Map 在导入后会自动为 matplotlib/cartopy 的 Axes 对象注册扩展方法,无需额外初始化。
5.1 ax.scontourf — 填充等值线
m = ax.scontourf(lon, lat, data, cmap='RdBu_r', levels=np.arange(-1.2, 1.4, 0.2), extend="both")| 参数 | 说明 |
|---|---|
lon, lat | 经纬度坐标 |
data | 二维数据数组 (lat, lon) |
cmap | 色标,如 'RdBu_r' |
levels | 等值线层级,可传入整数或 np.arange / np.linspace 生成的具体值 |
extend | 色标延伸:"both" 两端延伸,"min", "max", "neither" |
5.2 ax.scontour — 叠加等值线
在已有填充等值线上叠加黑色等值线:
ax.scontour(m, colors="black")| 参数 | 说明 |
|---|---|
m | scontourf 返回的对象,沿用其 levels |
colors | 等值线颜色,如 "black" |
5.3 ax.init_map — 地图初始化
自动添加海岸线、设置经纬度刻度:
ax.init_map(stepx=50, stepy=20, smallx=10, smally=5)| 参数 | 说明 |
|---|---|
stepx | 大刻度经度间隔(度) |
stepy | 大刻度纬度间隔(度) |
smallx | 小刻度经度间隔(度) |
smally | 小刻度纬度间隔(度) |
init_map等价于自动调用ax.coastlines()+ 经纬度刻度设置,简化了 cartopy 的绘图流程。
5.4 ax.sig_plot — 显著性打点
在图上对通过显著性检验的格点打点标记:
ax.sig_plot(lon, lat, p_value, thrshd=0.05, color='gray')| 参数 | 说明 |
|---|---|
lon, lat | 经纬度坐标 |
p_value | p 值场 (lat, lon) |
thrshd | 显著性阈值,如 0.05 或 0.10 |
color | 打点颜色,如 'gray' |
工作原理:将
p_value < thrshd的格点用指定颜色打点(散点),常用于回归图或合成图的显著性标记。
5.5 ax.squiver — 风场矢量图
在地图上叠加风场箭头(矢量):
ax.squiver(uwnd.lon, uwnd.lat, uwnd_tmp, vwnd_tmp, stepx=4, stepy=2, width=0.004)| 参数 | 说明 |
|---|---|
lon, lat | 风场格点的经纬度坐标 |
u, v | 纬向风和经向风分量 |
stepx | 经度方向间隔抽取(隔几个格点画一个箭头) |
stepy | 纬度方向间隔抽取 |
width | 箭头线宽 |
squiver自动处理间隔抽取,避免箭头过于密集。
5.6 绘图完整示例(来源:ENSO_regression_sacpy.py<24-32>24-32>)
import sacpy.Mapimport matplotlib.pyplot as pltimport cartopy.crs as ccrs
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))
# 填充等值线m = ax.scontourf(sst.lon, sst.lat, LinReg.slope, cmap='RdBu_r', extend="both")# 叠加等值线ax.scontour(m, colors="black")# 地图初始化ax.init_map(stepx=50, stepy=20, smallx=10, smally=5)# 设置地图范围ax.set_extent([0, 358, -60, 60])# 显著性打点ax.sig_plot(sst.lon, sst.lat, LinReg.p_value, thrshd=0.05, color='gray')ax.set_title("Nino34 Regression Map", fontsize=18)5.7 SST + 风场叠加绘图示例(来源:Nino12_regression_sst_uv_sacpy.py<46-76>46-76>)
fig = plt.figure(figsize=[9, 5])ax = fig.add_subplot(projection=ccrs.PlateCarree(central_longitude=180))
# 填充等值线(SST 回归系数)m1 = ax.scontourf(sst.lon, sst.lat, sst_tmp, cmap='RdBu_r', levels=np.arange(-1.2, 1.4, 0.2), extend="both")ax.init_map(stepx=50, stepy=20, smallx=10, smally=5)ax.set_extent([0, 358, -60, 60])
# 显著性打点ax.sig_plot(sst.lon, sst.lat, map_sst.p_value, thrshd=0.10, color='gray')
# 风场矢量叠加ax.squiver(uwnd.lon, uwnd.lat, uwnd_tmp, vwnd_tmp, stepx=4, stepy=2, width=0.004)
ax.set_title("SSTA Regression Map (Nino1+2)", fontsize=20)
# colorbarplt.colorbar(m1, orientation='horizontal', shrink=0.7)六、sacpy 与手动实现对比
| 功能 | 手动实现 | sacpy |
|---|---|---|
| 距平计算 | groupby('time.month').mean() → 相减 | scp.get_anom(data, method=1) |
| 线性回归 | np.linalg.lstsq + 手算 p 值 | scp.LinReg(index, field) |
| EOF 分析 | eofs.standard.Eof(data, weights) 逐步骤操作 | scp.EOF(data) → .solve() |
| 地图填充 | ax.contourf() + 手动 transform | ax.scontourf() 自动处理投影 |
| 显著性打点 | 手动 np.where + scatter | ax.sig_plot() 一行搞定 |
| 风场矢量 | ax.quiver() + 手动抽取 | ax.squiver() 自动抽取间隔 |
七、核心 API 速查表
| 需求 | 代码 |
|---|---|
| 去气候态 | scp.get_anom(sst, method=1) |
| 线性回归 | LinReg = scp.LinReg(index, field) |
| 回归系数 | LinReg.slope |
| 回归 p 值 | LinReg.p_value |
| EOF 初始化 | eof = scp.EOF(ssta) |
| EOF 求解 | eof.solve() |
| 获取 PC | pc = eof.get_pc(npt=3) |
| 获取模态 | pt = eof.get_pt(npt=3) |
| 方差占比 | pcvar = eof.get_varperc(npt=3) * 100 |
| 填充等值线 | ax.scontourf(lon, lat, data, cmap='RdBu_r', extend="both") |
| 叠加等值线 | ax.scontour(m, colors="black") |
| 地图初始化 | ax.init_map(stepx=50, stepy=20) |
| 显著性打点 | ax.sig_plot(lon, lat, p_value, thrshd=0.05, color='gray') |
| 风场矢量 | ax.squiver(lon, lat, u, v, stepx=4, stepy=2) |
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!



