sacpy的简单用法

1573 字
8 分钟
sacpy的简单用法

sacpy 使用方法指南#

本文档整理自 相关代码 目录中涉及 sacpy 的 Python 脚本,汇总了 sacpy 库在气象数据分析中的核心用法,包括距平计算、线性回归、EOF 分析及地图绘图增强。


一、安装#

Terminal window
pip install sacpy

二、距平计算 — scp.get_anom#

2.1 基本用法#

import sacpy as scp
ssta = scp.get_anom(sst, method=1)

2.2 参数说明#

参数说明
sstxarray DataArray,维度 (time, lat, lon)
method=1方法1:逐月去气候态(减去各月多年平均),即去季节循环

2.3 完整示例(来源:ENSO_regression_sacpy.py<16>#

import xarray as xr
import 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>#

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_valuep 值场,形状与 slope 一致

3.4 完整示例(来源:ENSO_regression_sacpy.py<18-21>#

# 计算 Nino34 指数
nino34 = sst.loc[:, 5:-5, 190:240].mean(dim=['lat', 'lon'])
# 线性回归:将 SST 场回归到 Nino34 指数
LinReg = scp.LinReg(nino34, sst)
slope = LinReg.slope
p_value = LinReg.p_value

3.5 多变量逐个回归(来源:Nino12_regression_sst_uv_sacpy.py<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>#

import xarray as xr
import 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>#

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import 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))
# colorbar
cb_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")
参数说明
mscontourf 返回的对象,沿用其 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_valuep 值场 (lat, lon)
thrshd显著性阈值,如 0.050.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>#

import sacpy.Map
import matplotlib.pyplot as plt
import 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>#

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)
# colorbar
plt.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() + 手动 transformax.scontourf() 自动处理投影
显著性打点手动 np.where + scatterax.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()
获取 PCpc = 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)

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

sacpy的简单用法
http://liuhuangzao.top/posts/python/sacpy/
作者
硫磺皂
发布于
2026-07-15
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
硫磺皂
干嘛
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:000:00
暂无歌词
分类
标签
站点统计
文章
8
分类
2
标签
5
总字数
13,914
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.13.10
文章许可
CC BY-NC-SA 4.0