sacpy使用指南

6499 字
32 分钟
sacpy使用指南

sacpy 文档合集#


安装

pip install sacpy

注意:必须用pip,该库没有发布在conda-forge中


经验正交函数(EOF)分析#


导入#

import numpy as np
import xarray as xr
from sacpy import EOF

class EOF#

EOF(经验正交函数)分析类,用于将时空场分解为空间模态和时间系数。

EOF(data, weights=None)#

作用:初始化 EOF 分析对象。

参数类型默认值说明
datanp.ndarray / xr.DataArray必需输入数据,形状 (time, *space)
weightsnp.ndarray / NoneNone空间权重,形状可广播至空间维度。常见用法:纬度余弦平方根权重 np.sqrt(cos(lat))

注意:若传入 xr.DataArray,内部会转为 numpy 数组。


solve(method="eig", st=False, dim_min=10, chunks=None)#

作用:求解 EOF,得到特征值和特征向量。

参数类型默认值说明
methodstr"eig"求解方法:
- "eig":协方差矩阵特征分解
- "svd":SVD 分解(适合 time < space 的情况)
- "dask_svd":使用 Dask 的 SVD(需 dask 库)
stboolFalse是否打印求解起止时间
dim_minint10eig 模式下的最小维度(SVD 模式自动取 min(time, space))
chunkstuple / NoneNonedask_svd 模式的块大小,必须提供

无返回值,结果保存在对象属性中。

使用示例

# 准备数据(异常场)
sst = xr.open_dataset('sst.nc')['sst']
sst_anom = sst - sst.groupby('time.month').mean('time')
# 纬度权重
coslat = np.cos(np.deg2rad(sst_anom['lat'].values))
# EOF 分析
eof_obj = EOF(sst_anom, weights=np.sqrt(coslat))
eof_obj.solve(method="eig")

get_eign(npt=4)#

作用:获取前 n 个特征值(未缩放)。

参数类型默认值说明
nptint4返回的特征值数量

返回np.ndarray,形状 (npt,)

使用示例

eign = eof_obj.get_eign(npt=3)

get_varperc(npt=None)#

作用:返回各模态解释的方差比例(0~1)。

参数类型默认值说明
nptint / NoneNone返回数量。None 返回所有

公式var_perc[i] = eigenvalue[i] / sum(variance_of_all_space_points)

返回np.ndarray,形状 (npt,)

使用示例

vf = eof_obj.get_varperc(npt=5)
print(vf) # 前5个模态的方差解释比例

north_test(npt=10, perc=False, ddof=None)#

作用:使用 North et al. (1982) 方法计算特征值的典型误差。

参数类型默认值说明
nptint10检验的模态数量
percboolFalse是否按总方差缩放(True 时误差尺度同 get_varperc
ddofint / NoneNone自由度。None 默认使用 time_length

返回np.ndarray,形状 (npt,)

使用示例

errors = eof_obj.north_test(npt=5)
evals = eof_obj.get_eign(5)
# 判断是否显著分离
for i in range(4):
if evals[i] - errors[i] > evals[i+1] + errors[i+1]:
print(f"模式 {i+1}{i+2} 分离良好")

get_pc(npt=None, scaling="std")#

作用:获取主成分时间序列(PCs)。

参数类型默认值说明
nptint / NoneNone返回的 PC 数量。None 返回所有
scalingstr"std"缩放方式:
- None:不缩放(原始 PC)
- "std":除以标准差,使每个 PC 方差为 1
- "DSE":除以 sqrt(特征值)
- "MSE":乘以 sqrt(特征值)

返回np.ndarray,形状 (npt, time)

使用示例

# 获取前3个标准化 PC
pcs = eof_obj.get_pc(npt=3, scaling="std")
# 获取所有未缩放 PC
pcs_raw = eof_obj.get_pc(scaling=None)
# 获取第1个 PC(E 型缩放)
pc1 = eof_obj.get_pc(npt=1, scaling="MSE")

get_pt(npt=None, scaling="mstd")#

作用:获取空间模态(patterns / EOFs)。

参数类型默认值说明
nptint / NoneNone返回的模式数量
scalingstr"mstd"缩放方式:
- None:不缩放(原始特征向量)
- "std"(即 "mstd"):乘以 PC 的标准差
- "DSE":除以特征值
- "MSE":乘以特征值

返回np.ndarray,形状 (npt, *origin_space_shape)

使用示例

# 获取前3个空间模态(与标准化PC匹配)
patterns = eof_obj.get_pt(npt=3, scaling="mstd")
# 获取原始特征向量(不缩放)
patterns_raw = eof_obj.get_pt(npt=3, scaling=None)

correlation_map(npt)#

作用:计算每个 EOF 模式对应的空间相关系数图(PC 与原始场每个格点的相关系数)。

参数类型默认值说明
nptint必需计算的模式数量

返回np.ndarray,形状 (npt, *origin_space_shape),值域 [-1, 1]

使用示例

corr_maps = eof_obj.correlation_map(npt=3)
# corr_maps[0] 为第1模态的相关系数空间分布

projection(proj_field, npt=None, scaling="std")#

作用:将新场投影到已有的 EOF 空间模态上,得到伪 PC。

参数类型默认值说明
proj_fieldnp.ndarray必需待投影场,形状 (time, *space)
nptint / NoneNone投影到前几个模态
scalingstr"std"PC 缩放方式(同 get_pcscaling

返回np.ndarray,形状 (npt, proj_time)

使用示例

# 将新的海温场投影到前3个 EOF 上
new_sst = xr.open_dataset('new_sst.nc')['sst'].values
pseudo_pcs = eof_obj.projection(new_sst, npt=3)

decoder(pcs)#

作用:用给定的 PC 和已有的空间模态重构原始场。

参数类型默认值说明
pcsnp.ndarray必需PC 序列,形状 (*time, pc_num)

返回np.ndarray,形状 (*time, *origin_space_shape)。若初始化时提供了 weights,重构时会自动除以权重。

使用示例

# 用第1个 PC 重构场
pc1 = eof_obj.get_pc(npt=1, scaling="std")
recon = eof_obj.decoder(pc1.T) # 注意 transpose
# recon 形状:(time, lat, lon)

load_pt(patterns)#

作用:从外部加载空间模态(用于解码等操作)。

参数类型默认值说明
patternsnp.ndarray必需空间模态,形状 (npt, *space)

使用示例

eof_obj.load_pt(precomputed_patterns)

完整示例:EOF 分析+绘图#

import numpy as np
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from sacpy import EOF
# 1. 数据准备
da = xr.open_dataset('sst.nc')['sst']
da_anom = da.groupby('time.month') - da.groupby('time.month').mean('time')
# 2. EOF 分析
coslat = np.cos(np.deg2rad(da_anom['lat'].values))
eof = EOF(da_anom, weights=np.sqrt(coslat))
eof.solve()
vf = eof.get_varperc()
print(f"EOF1 方差解释: {vf[0]:.2%}")
# 3. 获取结果
pc1 = eof.get_pc(npt=1, scaling="std") # (1, time)
pt1 = eof.get_pt(npt=1, scaling="mstd") # (1, lat, lon)
corr_map = eof.correlation_map(npt=1) # (1, lat, lon)
# 4. 绘图(使用 sacpy 的绘图扩展)
import sacpy.Map # 注册 GeoAxesSubplot 扩展方法
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=190))
c = ax.scontourf(da_anom['lon'], da_anom['lat'], corr_map[0],
cmap='RdBu_r')
ax.init_map(coastlines=True)
plt.colorbar(c, label='Correlation')
plt.title('EOF1 Correlation Map')
plt.show()

奇异值分解(SVD)/ 最大协方差分析(MCA)#


导入#

import numpy as np
import xarray as xr
from sacpy import SVD, MCA # MCA 是 SVD 的别名

class SVD#

SVD(奇异值分解)分析类,用于研究两个场之间的耦合关系。MCA 是其别名。

SVD(data1, data2, complex=False)#

作用:初始化 SVD 分析对象。

参数类型默认值说明
data1np.ndarray / xr.DataArray必需左场数据,形状 (time, *space1)
data2np.ndarray / xr.DataArray必需右场数据,形状 (time, *space2)
complexboolFalse是否使用复数类型

注意data1data2 的时间维度必须相等。


solve()#

作用:求解 SVD,计算协方差矩阵并分解。

无参数,无返回值。结果保存在对象属性中。

使用示例

svd_obj = SVD(sst_anom, precip_anom)
svd_obj.solve()

get_eign()#

作用:返回协方差矩阵的奇异值。

返回np.ndarray

使用示例

eign = svd_obj.get_eign()

get_varperc(npt)#

作用:返回各 SVD 模态的方差解释比例(基于奇异值平方的占比)。

参数类型默认值说明
nptint必需返回的模式数量

公式var_perc[i] = eign[i]^2 / sum(eign^2)

返回np.ndarray,形状 (npt,)

使用示例

vf = svd_obj.get_varperc(npt=5)

get_pc(npt, norm="std")#

作用:获取左场和右场的时间系数(expansion coefficients)。

参数类型默认值说明
nptint必需返回的模式数量
normstr"std"标准化方式:
- "std":除以各自的标准差
- 其他值:不做标准化

返回(pc_left, pc_right),均为 np.ndarray,形状 (npt, time)

使用示例

pc_left, pc_right = svd_obj.get_pc(npt=3, norm="std")

get_pt(npt, norm="std")#

作用:获取左场和右场的空间模态(SVD patterns)。

参数类型默认值说明
nptint必需返回的模式数量
normstr"std"标准化方式。"std" 时乘以对应 PC 的标准差

返回(patterns_left, patterns_right),形状分别为 (npt, *space1)(npt, *space2)

使用示例

pt_left, pt_right = svd_obj.get_pt(npt=3)
# pt_left 形状: (3, lat1, lon1)
# pt_right 形状: (3, lat2, lon2)

get_homogeneous_map(npt=3, norm="std")#

作用:获取齐次相关图(homogeneous correlation map)—— 每个 SVD 模态的 PC 与自身场之间的线性回归图。

参数类型默认值说明
nptint3计算的模式数量
normstr"std"标准化方式

返回(map_left, map_right),形状同 get_pt

使用示例

homo_left, homo_right = svd_obj.get_homogeneous_map(npt=3)

get_heterogeneous_map(npt=3, norm="std")#

作用:获取非齐次相关图(heterogeneous correlation map)—— 左场 PC 与右场数据的回归图,以及右场 PC 与左场数据的回归图。

参数类型默认值说明
nptint3计算的模式数量
normstr"std"标准化方式

返回(map_left, map_right)

使用示例

hetero_left, hetero_right = svd_obj.get_heterogeneous_map(npt=3)

注意:当前实现中 get_homogeneous_mapget_heterogeneous_map 逻辑相同,均返回 PC 与对应原始场的回归系数图。


get_var_contribution(npt=3)#

作用:计算各 SVD 模态对左场和右场总方差的贡献比例。

参数类型默认值说明
nptint3计算的模式数量

返回(left_var, right_var),均为 np.ndarray,形状 (npt,)

公式var[i] = sum(PC_i^2) / sum(data^2)

使用示例

left_contrib, right_contrib = svd_obj.get_var_contribution(npt=3)
print(f"SVD1 对左场方差贡献: {left_contrib[0]:.2%}")
print(f"SVD1 对右场方差贡献: {right_contrib[0]:.2%}")

完整示例:SVD 分析#

import numpy as np
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from sacpy import SVD, get_anom
# 1. 数据准备
sst = xr.open_dataset('sst.nc')['sst']
precip = xr.open_dataset('precip.nc')['precip']
sst_anom = get_anom(sst) # (time, lat, lon)
precip_anom = get_anom(precip) # (time, lat, lon)
# 2. SVD 分析
svd = SVD(sst_anom, precip_anom)
svd.solve()
# 3. 获取结果
pc_left, pc_right = svd.get_pc(npt=3, norm="std")
hetero_left, hetero_right = svd.get_heterogeneous_map(npt=2)
# 4. 绘图 - 第1 SVD 模态的非齐次相关图
import sacpy.Map
fig, axes = plt.subplots(1, 2, subplot_kw={
'projection': ccrs.PlateCarree(central_longitude=190)
})
ax = axes[0]
c = ax.scontourf(sst_anom['lon'], sst_anom['lat'], hetero_left[0],
cmap='RdBu_r', extent='both')
ax.init_map(coastlines=True)
ax.set_title('Heterogeneous Map (SST ← Precip PC)')
ax = axes[1]
c = ax.scontourf(precip_anom['lon'], precip_anom['lat'], hetero_right[0],
cmap='RdBu_r', extent='both')
ax.init_map(coastlines=True)
ax.set_title('Heterogeneous Map (Precip ← SST PC)')
plt.show()

线性回归#


导入#

import numpy as np
import xarray as xr
from sacpy import LinReg, MultLinReg
# 或直接使用底层函数
from sacpy.linger_cal import linear_reg, multi_linreg, multi_corr, partial_corr

class LinReg#

一元线性回归类。

LinReg(x, y, neff=None)#

作用:进行一元线性回归 y = slope * x + intercept

参数类型默认值说明
xnp.ndarray / xr.DataArray必需自变量(预测因子),形状 (time,)
ynp.ndarray / xr.DataArray必需因变量(响应变量),形状 (time, *space)
neffint / NoneNone有效自由度(用于 T 检验)。None 时使用 time-2

属性

属性类型说明
slopenp.ndarray / xr.DataArray回归斜率,形状 (*space)
intcptnp.ndarray / xr.DataArray截距,形状 (*space)
corrnp.ndarray / xr.DataArray相关系数,形状 (*space),值域 [-1, 1]
p_valuenp.ndarray / xr.DataArrayp 值(双尾 T 检验),形状 (*space)

使用示例

# 对 ENSO 指数与海温场做回归
enso_idx = enso_idx # shape: (time,)
reg = LinReg(enso_idx, sst_anom)
# 获取回归系数
slope_map = reg.slope # shape: (lat, lon)
corr_map = reg.corr # 相关系数
pval_map = reg.p_value # 显著性
# 若输入为 xr.DataArray,输出自动保留坐标

LinReg.mask(threshold=0.05)#

作用:按 p 值阈值掩码不显著区域。

参数类型默认值说明
thresholdfloat0.05p 值阈值,超过此值的格点设为 NaN

无返回值,生成三个新属性:slope1intcpt1corr1

使用示例

reg.mask(threshold=0.05)
# 使用 reg.slope1 / reg.corr1 获取仅显著区域的回归图

class MultLinReg#

多元线性回归类。

MultLinReg(x, y, cal_sim=True)#

作用:进行多元线性回归 y = slope[0]*x[0] + slope[1]*x[1] + ... + intercept

参数类型默认值说明
xnp.ndarray / xr.DataArray必需因子矩阵,形状 (time, N_factor)
ynp.ndarray / xr.DataArray必需因变量,形状 (time, *space)
cal_simboolTrue是否在初始化时自动计算回归结果

属性

属性类型说明
slopenp.ndarray回归系数,形状 (N_factor, *space)
intcptnp.ndarray截距,形状 (*space)
Rnp.ndarray复相关系数,形状 (*space)
pv_allnp.ndarray整体 F 检验 p 值,形状 (*space)
pv_inp.ndarray各因子 F 检验 p 值,形状 (N_factor, *space)

使用示例

# 三个因子对海温的多元回归
factors = np.column_stack([enso, pdo, amo]) # (time, 3)
reg_m = MultLinReg(factors, sst_anom)
# ENSO 单独的回归系数场
enso_slope = reg_m.slope[0] # 第1个因子的斜率场
enso_pval = reg_m.pv_i[0] # 第1个因子的 p 值场

MultLinReg.cal_corr()#

作用:计算所有因子与因变量之间的相关系数矩阵。

返回np.ndarray,形状 (*space, N_factor+1, N_factor+1),最后两个维度为相关矩阵。

MultLinReg.cal_paritial_corr(idx)#

作用:计算第 idx 个因子与因变量的偏相关系数(排除其他因子影响)。

参数类型默认值说明
idxint必需因子的索引(0-based)

返回np.ndarray,形状 (*space)

使用示例

# 计算 ENSO 的偏相关(排除 PDO 和 AMO 的影响)
reg_m.cal_corr() # 先计算相关系数矩阵
partial_r = reg_m.cal_paritial_corr(idx=0)

class M2mLinReg#

多变量对多变量的相关分析类。

M2mLinReg(x, y)#

作用:计算两组多变量时间序列之间的相关系数矩阵。

参数类型默认值说明
xnp.ndarray必需形状 (time, N_factor)
ynp.ndarray必需形状 (time, M_factor)

属性

属性类型说明
corrnp.ndarray相关系数矩阵,形状 (N_factor, M_factor)
p_valuenp.ndarrayp 值矩阵,形状 (N_factor, M_factor)

使用示例

m2m = M2mLinReg(factors, pcs) # factors: (time, 3), pcs: (time, 5)
print(m2m.corr) # (3, 5) 相关系数矩阵
print(m2m.p_value) # 显著性矩阵

class SpaceCorr#

空间相关类。

SpaceCorr(x, y)#

作用:计算两个同形状空间场之间的逐点相关系数。

参数类型默认值说明
xnp.ndarray必需形状 (time, *space)
ynp.ndarray必需形状 (time, *space)

属性

属性类型说明
corrnp.ndarray逐点相关系数,形状 (*space)

底层函数#

这些函数是 LinRegMultLinReg 的底层实现,可直接调用。

linear_reg(x, y, neff=None)#

等同 LinReg(x, y, neff)。返回 (slope, intcpt, corr, p_value)

multi_linreg(x, y)#

等同 MultLinReg(x, y)。返回 (slope, intcpt, R, pv_all, pv_i)

partial_corr(x, y, idx, mul_corr=None)#

等同 MultLinReg.cal_paritial_corr(idx)

multi_corr(x, y)#

等同 MultLinReg.cal_corr()


完整示例#

import numpy as np
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from sacpy import LinReg, MultLinReg
import sacpy.Map
# 一元回归 + 绘图
da = xr.open_dataset('sst.nc')['sst']
enso = np.random.randn(da.shape[0])
reg = LinReg(enso, da)
reg.mask(0.05)
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=190))
c = ax.scontourf(da['lon'], da['lat'], reg.slope1, cmap='RdBu_r')
ax.sig_plot(da['lon'], da['lat'], reg.p_value, marker='..')
ax.init_map(coastlines=True)
plt.colorbar(c, label='Regression slope')
plt.title('ENSO Regression on SST (p<0.05 dotted)')
plt.show()

显著性检验#


导入#

import numpy as np
import xarray as xr
from sacpy import STMV
# 或直接使用底层函数
from sacpy.SigTest import one_mean_test, two_mean_test

class STMV#

均值的显著性 T 检验类(Significance Test of Mean Value)。自动判断单样本或双样本检验。

STMV(data1, data2=None, wrap=True, *param, **kwargs)#

作用:对数据执行 T 检验。

参数类型默认值说明
data1np.ndarray / xr.DataArray必需第一组数据,形状 (time, *space)
data2np.ndarray / xr.DataArray / NoneNone第二组数据。None 时进行单样本 T 检验(与 0 比较);否则进行双样本 T 检验
wrapboolTrue是否将结果包装为 xr.DataArray(需输入为 DataArray)
*param--传递给 scipy.stats.ttest_1sampttest_ind 的额外参数

属性

属性类型说明
meannp.ndarray / xr.DataArray单样本时为 data1 均值,双样本时为 mean(data1) - mean(data2)
p_valuenp.ndarray / xr.DataArrayp 值,形状 (*space)

使用示例

# 单样本检验:检验异常场是否显著偏离 0
stmv = STMV(sst_anom)
print(stmv.mean) # 时间平均场
print(stmv.p_value) # 显著性水平
# 双样本检验:两组数据均值差检验
stmv2 = STMV(sst_early, sst_late)
print(stmv2.mean) # 均值差(late - early?实际是 early - late)
print(stmv2.p_value) # 显著性

STMV.get_original_data()#

作用:获取原始输入数据。

返回:单样本时返回 data1,双样本时返回 (data1, data2)


one_mean_test(data, expected_mean=None, *param)#

作用:单样本 T 检验(底层函数)。检验 data 的均值是否等于 expected_mean

参数类型默认值说明
datanp.ndarray / xr.DataArray必需待检验数据,形状 (time, *space)
expected_meannp.ndarray / NoneNone期望均值。None 表示与 0 比较
*param--传递给 scipy.stats.ttest_1samp

返回(origin_mean, pvalue)origin_mean 为数据均值。

使用示例

mean, pval = one_mean_test(sst_anom)

two_mean_test(data1, data2, *param)#

作用:双样本独立 T 检验(底层函数)。检验两组数据均值是否相等。

参数类型默认值说明
data1np.ndarray / xr.DataArray必需第一组数据,形状 (time1, *space)
data2np.ndarray / xr.DataArray必需第二组数据,形状 (time2, *space)
*param--传递给 scipy.stats.ttest_ind

返回(mean_diff, pvalue)mean_diff = mean(data1) - mean(data2)

使用示例

mean_diff, pval = two_mean_test(sst_1950_1980, sst_1980_2010)

完整示例:年代际差异检验+绘图#

import numpy as np
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from sacpy import STMV, get_anom
import sacpy.Map
# 数据
sst = xr.open_dataset('sst.nc')['sst']
early = sst.sel(time=slice('1950', '1980'))
late = sst.sel(time=slice('1985', '2015'))
# 双样本 T 检验
stmv = STMV(late, early)
# 绘图
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=190))
c = ax.scontourf(sst['lon'], sst['lat'], stmv.mean, cmap='RdBu_r')
ax.sig_plot(sst['lon'], sst['lat'], stmv.p_value, marker='..')
ax.init_map(coastlines=True)
plt.colorbar(c, label='SST Difference (late - early)')
plt.title('SST Change between 1950-1980 and 1985-2015')
plt.show()

谱分析#


导入#

import numpy as np
from sacpy import Spectral, CrossSpectral

class Spectral#

单变量功率谱分析类(基于 Welch 方法 / WOSA)。

Spectral(x, M_length, overlap=0.5, remove_trend=True, remove_annual=True, normalize_series=True, prewhiten=False)#

作用:初始化谱分析对象并预处理时间序列。

参数类型默认值说明
xnp.ndarray必需一维时间序列
M_lengthint必需WOSA 分段长度,最好为 2 的幂
overlapfloat0.5分段重叠比例。若数据按季节分割,建议设为 0
remove_trendboolTrue是否去除线性趋势
remove_annualboolTrue是否去除年循环(harmonic fit)
normalize_seriesboolTrue是否标准化序列(方差=1)
prewhitenboolFalse是否预白化处理

属性

属性类型说明
dfnfloat谱的保守自由度估计(分子)
dfdfloat零假设的分母自由度
ac_xfloat预处理后序列的自相关系数

使用示例

# 准备一维时间序列
ts = monthly_sst.mean(dim=('lon', 'lat')).values # 长度为 N
# 初始化(保留趋势但去除年循环)
spec = Spectral(ts, M_length=64, remove_annual=True, remove_trend=False)

Spectral.get_spectra(normalize_spectrum=True, detrend='linear', **kwargs)#

作用:计算功率谱。

参数类型默认值说明
normalize_spectrumboolTrue是否将谱除以均值(便于比较)
detrendstr'linear'Welch 方法的去趋势设置
**kwargs--传递给 scipy.signal.welch 的额外参数

返回(f, Pxx) — 频率数组和功率谱。

使用示例

f, Pxx = spec.get_spectra()

Spectral.get_red_noise(method='fit_theory')#

作用:拟合红噪声谱。

参数类型默认值说明
methodstr'fit_theory'拟合方法:
- 'fit_theory':基于自相关系数理论计算
- 'fit_data':对观测谱做曲线拟合

返回np.ndarray,红噪声谱。

使用示例

red_noise = spec.get_red_noise(method='fit_theory')

Spectral.get_rs_sig(p_crit=0.99)#

作用:获取基于红噪声理论的显著性水平曲线。

参数类型默认值说明
p_critfloat0.99显著性水平(F 检验)

返回np.ndarray,显著谱值阈值曲线。

使用示例

sig_level = spec.get_rs_sig(p_crit=0.95)
# 功率谱高于 sig_level 的频率段为显著

class CrossSpectral(Spectral)#

交叉谱分析类,继承自 Spectral

CrossSpectral(x, y, M_length, overlap=0.5, ...)#

作用:对两个时间序列进行交叉谱分析。

参数类型默认值说明
xnp.ndarray必需第一组一维时间序列
ynp.ndarray必需第二组一维时间序列

其余参数同 Spectral.__init__

新增属性ac_y(y 序列的自相关系数)。

CrossSpectral.get_spectra(normalize_spectrum=True, detrend='linear', **kwargs)#

作用:计算两个序列各自的功率谱。

返回(f, Pxx, Pyy)

CrossSpectral.get_red_noise(method='fit_theory')#

作用:拟合两个序列的红噪声谱。

返回(rsx, rsy)

CrossSpectral.get_rs_sig(p_crit=0.99)#

作用:获取两个序列的显著谱阈值。

返回(rsx_sig, rsy_sig)

CrossSpectral.get_cross_spectra(detrend='linear', **kwargs)#

作用:计算交叉谱(协方差谱、相位谱、凝聚谱)。

返回(covariance, phase, coherence)

返回值说明
covariance协方差谱(cross-spectrum 实部)
phase相位谱(角度制)
coherence凝聚谱(0~1)

使用示例

cov, phase, coh = cross_spec.get_cross_spectra()

CrossSpectral.get_coh_sig(p_crit=0.99)#

作用:获取凝聚谱的显著性水平。

参数类型默认值说明
p_critfloat0.99显著性水平

返回float,凝聚谱显著性阈值。

辅助函数#

autocorr(x)#

作用:计算时间序列的滞后-1 自相关系数。

参数类型默认值说明
xnp.ndarray必需一维时间序列

返回float

from sacpy.spectral import autocorr
ac = autocorr(ts)

完整示例:单变量谱分析#

import numpy as np
import matplotlib.pyplot as plt
from sacpy import Spectral
# 准备数据
ts = sst_anom.mean(dim=('lat', 'lon')).values # 区域平均 SSTA
# 谱分析
spec = Spectral(ts, M_length=64, remove_annual=True)
# 计算谱
f, Pxx = spec.get_spectra()
red = spec.get_red_noise()
sig = spec.get_rs_sig(p_crit=0.95)
# 绘图
plt.figure(figsize=(10, 4))
plt.semilogx(1/f, f*Pxx, 'b-', linewidth=1.5, label='Power Spectrum')
plt.semilogx(1/f, f*red, 'r--', label='Red Noise')
plt.semilogx(1/f, f*sig, 'r:', linewidth=0.5, label='95% Significance')
plt.xlabel('Period')
plt.ylabel('Frequency x Power')
plt.legend()
plt.title('Power Spectrum')
plt.show()

完整示例:交叉谱分析#

import numpy as np
import matplotlib.pyplot as plt
from sacpy import CrossSpectral
# 两个时间序列
ts1 = enso_index
ts2 = precip_index
cross = CrossSpectral(ts1, ts2, M_length=64)
f, Pxx, Pyy = cross.get_spectra()
cov, phase, coh = cross.get_cross_spectra()
coh_sig = cross.get_coh_sig(p_crit=0.95)
fig, axes = plt.subplots(3, 1, figsize=(10, 8), sharex=True)
axes[0].semilogx(1/f, f*Pxx, label='x')
axes[0].semilogx(1/f, f*Pyy, label='y')
axes[0].set_ylabel('Power')
axes[0].legend()
axes[1].semilogx(1/f, coh)
axes[1].axhline(coh_sig, color='r', linestyle='--', label='95% Sig')
axes[1].set_ylabel('Coherence')
axes[1].set_ylim(0, 1)
axes[2].semilogx(1/f, phase)
axes[2].set_ylabel('Phase (°)')
axes[2].set_xlabel('Period')
plt.suptitle('Cross-Spectral Analysis')
plt.show()

地图绘图#


导入#

绘图扩展通过 import sacpy.Map 即可自动注册到 GeoAxesSubplot 上:

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import numpy as np
import xarray as xr
import sacpy.Map # 注册所有绘图扩展方法

同时也可直接使用工具函数:

from sacpy.Map import get_levels
from sacpy.settings import Map as MapSettings

绘图风格配置#

导入 sacpy.Map 时会自动设置:

  • 字体:Times New Roman
  • 默认 colormap:RdBu_r

如需自定义,可在导入后修改 matplotlibrcParams


get_levels(data, percentile=98, num_level=13, zero_sym=True)#

作用:根据数据分布自动生成等值线/填色层级。

参数类型默认值说明
datanp.ndarray必需待绘制数据
percentileint98最高/最低值的百分位数(截断极端值)
num_levelint13层级数量
zero_symboolTrue是否以零为中心对称

返回np.ndarray,等间距的层级数组。

使用示例

levels = get_levels(corr_map, percentile=95, num_level=11, zero_sym=True)

GeoAxesSubplot 扩展方法#

sacpy.Mapcartopy.mpl.geoaxes.GeoAxesSubplot 进行了 monkey-patch,新增以下方法:

scontourf(*args, **kwargs)#

作用:智能填色图(contourf)。自动处理层级、colormap 和坐标转换。

参数类型说明
*args1~4 个参数支持多种传入方式:
- (Z):仅数据(需后续设置坐标)
- (Z, levels)
- (x, y, Z):经纬度+数据
- (x, y, Z, levels)

新增的 kwargs

参数类型默认值说明
percentileint98自动层级时的百分位
num_levelint13自动层级时的层级数
zero_symboolTrue层级是否零对称
extendstr"both"色棒延伸方向
cmapstr"RdBu_r"colormap
transformcrsPlateCarree()数据坐标系统

返回matplotlib.contour.QuadContourSet

使用示例

ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=190))
c = ax.scontourf(lon, lat, sst_map)
# 或自动层级
c = ax.scontourf(lon, lat, sst_map, percentile=95, num_level=11)

spcolormesh(*args, **kwargs)#

作用:智能 pcolormesh。参数与 scontourf 类似,但使用 vmin/vmax 控制色彩范围。

返回matplotlib.collections.QuadMesh

使用示例

m = ax.spcolormesh(lon, lat, data, cmap='coolwarm')

scontour(*args, **kwargs)#

作用:智能等值线(contour)。自动添加 transform=ccrs.PlateCarree()

返回matplotlib.contour.QuadContourSet

squiver(*args, **kwargs)#

作用:智能风场图(quiver)。支持抽样步长。

新增 kwargs

参数类型默认值说明
stepxint1x 方向抽样步长
stepyint1y 方向抽样步长

使用示例

# 每5个格点画一个箭头
ax.squiver(lon, lat, u, v, stepx=5, stepy=5)

init_map(same_size=True, coastlines=True, draw_ticks=True, **kwargs)#

作用:快速初始化地图(画海岸线 + 设置刻度 + 固定宽高比)。

参数类型默认值说明
same_sizeboolTrue是否设置 set_aspect("auto")
coastlinesboolTrue是否绘制海岸线
draw_ticksboolTrue是否自动绘制刻度

额外传递给 draw_ticks 的 kwargs

参数类型默认值说明
stepxint / None自动大刻度 X 步长
stepyint / None自动大刻度 Y 步长
smallxint / None自动小刻度 X 步长
smallyint / None自动小刻度 Y 步长

使用示例

ax = plt.axes(projection=ccrs.PlateCarree())
ax.scontourf(lon, lat, data)
ax.init_map() # 自动海岸线+刻度

draw_ticks(extend, stepx=None, stepy=None, ...)#

作用:为地图添加经纬度刻度。

参数类型默认值说明
extendlist必需[xmin, xmax, ymin, ymax]
stepx / stepyint / None自动大刻度步长
smallx / smallyint / None自动小刻度步长

使用示例

ax.draw_ticks([-180, 180, -90, 90], stepx=30, stepy=15)

sig_plot(x, y, pvalue, thrshd=0.05, marker="..", color=None)#

作用:显著性打点(在显著区域叠加点/影线)。

参数类型默认值说明
xnp.ndarray必需经度
ynp.ndarray必需纬度
pvaluenp.ndarray必需p 值场,形状同数据
thrshdfloat0.05显著性阈值
markerstr".."影线样式(hatch pattern)
colorstr / NoneNone打点颜色

使用示例

ax.scontourf(lon, lat, data)
ax.sig_plot(lon, lat, p_value, marker='..', color='k')

sig_plot 同样注册到了 matplotlib.axes.Axes(非地图 Axes 可用,不带 transform)。


xr.DataArray.splot(ax=None, label=0, projection=None, kw1={}, kw2={})#

作用:DataArray 的快速绘图方法(需 2D 数据)。

参数类型默认值说明
axAxes / NoneNone坐标轴。None 自动创建
labelint0经纬度命名:0 = lon/lat1 = longitude/latitude
projectioncrs / NoneNone地图投影。None 自动使用 PlateCarree
kw1dict{}传递给 scontourf 的参数
kw2dict{}传递给 init_map 的参数

返回(m, ax) — 填色图对象和坐标轴。

使用示例

da = sst.isel(time=0) # 2D: (lat, lon)
m, ax = da.splot(kw1={'cmap': 'coolwarm', 'extend': 'both'})
plt.title('SST')
plt.show()

class Map(配置)#

sacpy.settings.Map 提供了常用 cartopy 投影的字典:

from sacpy.settings import Map
proj = Map.projection_dict['Robinson'](central_longitude=180)
proj = Map.projection_dict['Orthographic'](central_longitude=-20, central_latitude=60)

支持的投影名称:Robinson, PlateCarree, Mollweide, Orthographic, Mercator, Miller, LambertConformal, NorthPolarStereo, SouthPolarStereo 等 30+ 种。


完整示例#

import numpy as np
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import sacpy.Map
from sacpy.Map import get_levels
# 准备数据
da = xr.open_dataset('sst.nc')['sst'].isel(time=0) # 2D 场
lon, lat = da['lon'].values, da['lat'].values
# 创建地图
proj = ccrs.PlateCarree(central_longitude=180)
fig, axes = plt.subplots(2, 2, figsize=(14, 8),
subplot_kw={'projection': proj})
axes = axes.flatten()
# 子图1:智能填色 + 陆地 + 显著性打点
ax = axes[0]
c = ax.scontourf(lon, lat, da.values, cmap='RdBu_r',
percentile=98, num_level=13)
ax.add_feature(cfeature.LAND, facecolor='lightgray')
ax.init_map(coastlines=False)
plt.colorbar(c, ax=ax, label='SST')
# 子图2:pcolormesh
ax = axes[1]
m = ax.spcolormesh(lon, lat, da.values, cmap='coolwarm')
ax.init_map()
plt.colorbar(m, ax=ax)
# 子图3:使用 DataArray.splot
ax = axes[2]
m, _ = da.splot(ax=ax, kw1={'cmap': 'RdBu_r'})
ax.set_title('splot method')
# 子图4:不同投影
ax = axes[3]
proj2 = ccrs.Orthographic(central_longitude=180, central_latitude=0)
ax.remove()
ax = fig.add_subplot(2, 2, 4, projection=proj2)
c = ax.scontourf(lon, lat, da.values, cmap='RdBu_r')
ax.coastlines()
ax.set_global()
plt.colorbar(c, ax=ax, shrink=0.6)
plt.tight_layout()
plt.show()

数据处理工具#


导入#

from sacpy import get_anom, spec_moth_dat, spec_moth_yrmean
from sacpy import convert_lon, reverse_lon, field_corr, autocorr, sig_scatter
from sacpy.Util import gradient_da, shp_mask, gradient_array, ddof, rewapper
from sacpy.linger_cal import linear_reg, multi_linreg, multi_corr, partial_corr

get_anom(DaArray, method=0, freq="month", time_coords="time")#

作用:计算气候数据的距平(anomaly)。

参数类型默认值说明
DaArrayxr.DataArray必需输入数据,形状 (time, *space)
methodint0距平计算方法:
- 0:减去对应月份/日期的多年平均值
- 1:去除对应月份/日期的线性趋势
freqstr"month"时间频率:"month""day"
time_coordsstr"time"时间坐标名称

返回xr.DataArray,距平场。

使用示例

sst_anom = get_anom(sst, method=0, freq="month")

spec_moth_dat(DaArray, months)#

作用:提取特定月份的数据。

参数类型默认值说明
DaArrayxr.DataArray必需输入数据
monthslist / str必需月份列表 [12, 1, 2] 或季节名称 "DJF", "MAM", "JJA", "SON"

返回xr.DataArray,仅含指定月份的数据。

使用示例

djf_sst = spec_moth_dat(sst, "DJF") # 冬季数据
jja_sst = spec_moth_dat(sst, [6, 7, 8]) # 夏季数据

spec_moth_yrmean(DaArray, months)#

作用:提取特定月份数据并按年求平均。

参数类型默认值说明
DaArrayxr.DataArray必需输入数据
monthslist / str必需spec_moth_dat

返回xr.DataArray,每年一个值(季节均值)。

使用示例

djf_mean = spec_moth_yrmean(sst, "DJF") # 每年一个冬季平均
# 时间坐标变为年份

convert_lon(lon)#

作用:将经度从 [0, 360] 转换为 [-180, 180]

参数类型默认值说明
lonnp.ndarray必需经度数组

返回np.ndarray


reverse_lon(lon)#

作用:将经度从 [-180, 180] 转换为 [0, 360]


field_corr(field1, field2)#

作用:计算两个时空场的逐空间点相关系数。

参数类型默认值说明
field1np.ndarray必需形状 (time, *space)
field2np.ndarray必需形状 (time, *space),时间维度须与 field1 相同

返回np.ndarray,逐点相关系数,形状 (*space)

使用示例

corr_map = field_corr(sst, precip)

autocorr(x, lags)#

作用:计算多维数据的滞后自相关(2D 输入,第一维为时间)。

参数类型默认值说明
xnp.ndarray必需形状 (time, *space)
lagsint必需滞后期数

返回np.ndarray,形状 (*space)

注意:此为 Util.autocorr(带 lags 参数的多维版本),与 spectral.autocorr(一维滞后-1)不同。


sig_scatter(ax, x, y, p, threshold=0.05, **kwargs)#

作用:绘制显著散点图,不显著的点被遮蔽。

参数类型默认值说明
axAxes必需matplotlib 坐标轴
xnp.ndarray必需1D 数组
ynp.ndarray必需1D 数组
pnp.ndarray必需p 值数组
thresholdfloat0.05显著性阈值

返回PathCollection(散点图对象)。

使用示例

sig_scatter(ax, enso, precip, p_values, threshold=0.05, color='red', marker='o')

gradient_da(da, dim, method=0, delta=None)#

作用:计算 DataArray 沿某维度的梯度(差分)。

参数类型默认值说明
daxr.DataArray必需输入数据
dimstr必需求梯度的维度(如 "lat", "lon"
methodint00:中心差分(默认)。1:前向差分
deltafloat / NoneNone网格间距(m)。None 时自动根据 dim 估算

返回xr.DataArray

使用示例

dT_dy = gradient_da(sst, "lat") # 经向梯度

shp_mask(shp, Dataarray, lat='lat', lon='lon')#

作用:用 shapefile 掩码 DataArray(保留多边形内部区域)。

参数类型默认值说明
shpGeoDataFrame必需geopandas 读入的 shapefile
Dataarrayxr.DataArray必需待掩码数据
latstr"lat"纬度坐标名
lonstr"lon"经度坐标名

返回xr.DataArray,区域外的格点设为 NaN。

需要geopandasrioxarrayshapely

使用示例

import geopandas as gpd
shp = gpd.read_file('china.shp')
sst_china = shp_mask(shp, sst)

rewapper(data, origin_dataarray, drop_dims=None)#

作用:将计算结果重新包装为 xr.DataArray,保留原始坐标信息。

参数类型默认值说明
datanp.ndarray必需待包装数据
origin_dataarrayxr.DataArray必需原始 DataArray(用于提取坐标和维度)
drop_dimsstr / list / NoneNone需删除的维度(如原始数据的 time 维已被压缩)

注意:此函数处于早期开发阶段,可能不够稳定。


完整示例:数据处理流水线#

import xarray as xr
import numpy as np
from sacpy import get_anom, spec_moth_dat, spec_moth_yrmean, convert_lon
# 加载数据
ds = xr.open_dataset('era5_monthly.nc')
# 经度转换(0-360 → -180~180)
ds = ds.assign_coords(lon=convert_lon(ds['lon'].values)).sortby('lon')
# 计算距平
t_anom = get_anom(ds['t2m'], method=0, freq='month')
# 提取冬季并计算年平均值
djf_t = spec_moth_yrmean(t_anom, "DJF") # 每年冬季平均
# 提取夏季
jja_t = get_anom(spec_moth_dat(ds['t2m'], "JJA"))
print(djf_t)

文章分享

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

sacpy使用指南
http://liuhuangzao.top/posts/python/sacpy使用指南/
作者
硫磺皂
发布于
2026-07-16
许可协议
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