简介:针对降水、气温等气象时间序列的周期分析需求,这份MATLAB资源以小波功率谱为核心方法,面向气象、气候领域的学生与科研人员,帮助读者识别数据中的局部周期性与瞬态变化特征。压缩包共28个文件,以.m脚本为主体,涵盖小波变换、功率谱计算、显著性检验等环节;同时配有png结果图、txt/dat示例数据及bak/asv备份文件,整体仅184KB,轻量便于学习。目前已有2144人学习,对初、中级研究者颇为友好。内容提供可直接运行的Morlet小波分析代码,并集成太阳黑子、Nino海温等经典示例数据,能够复现小波功率谱图及95%显著性检验结果;脚本模块划分清晰,小波系数计算与显著性检验等函数可单独提取复用,适合快速迁移到自有降水、气温序列中完成周期分析与可视化。无论是验证经典算例还是替换自己的数据,都有较强的参考价值。 做降水、气温序列的周期分析时,很多人习惯直接上傅里叶变换或滑动平均,但真面临一段四十年的逐月资料,想知道“某个周期信号到底哪几年强、哪几年弱”的时候,传统方法就不太够用了。小波功率谱的好处在于,它能把时间维度和周期尺度同时铺在一张图上,让你既看到存在哪些显著周期,又能看出这些周期在时间轴上是稳定存在还是阶段性出现。这篇文章就基于小波功率谱在降水、气温等气象要素周期分析中的实际用法,把原理、参数、代码和容易踩的坑一次讲透。
适合的读者很明确:正在处理气象水文观测序列的研究生、做气候诊断分析的从业者,以及想把周期分析做得更扎实的跨领域数据分析人员。看完你至少能回答这几个问题——为什么要用小波而不是纯傅里叶、Morlet参数怎么定、显著性检验怎么落地、结果图上的“白化区域”为什么不能解读。
1. 为什么周期分析绕不开小波功率谱——从一次实际分析说起
1.1 傅里叶功率谱的“全局平均”缺陷
先讲个真实场景。我早年在分析某站近40年逐月降水资料时,按惯例先做了傅里叶功率谱,看到2~4年周期有一个明显峰值,高高兴兴准备下结论。但后来把序列按年代分成几段分别做功率谱,发现这个峰值在前20年非常强,后20年几乎消失。这就暴露了傅里叶变换的本质问题:它把整段时间序列拆成一组固定频率的正余弦波,得到的是整个时间跨度上的“平均”谱贡献,某个周期信号是持续存在还是只在某些年份出现,它完全区分不了。
对于降水这类受季风、海温、大气环流共同影响的要素,周期信号经常是非平稳的。比如东亚夏季风降水的准两年周期振荡,在某些年代强、某些年代弱,和ENSO的位相锁定关系也随年代变化。如果用傅里叶功率谱,你只能得到一个“平均强度”的峰,没法知道这个信号什么时候强、什么时候弱,更没法把周期变化和具体年份的气候异常事件对应起来。
1.2 小波变换的直观理解:给信号加一个可变焦距镜头
小波变换的思路可以理解成一个自带变焦镜头的扫描仪。母小波是一个能量集中在某一局部区域的波形,通过对它做平移和伸缩,就能用不同“宽度”的波去匹配序列中不同尺度的波动:尺度小的时候,小波在时间上压缩,频率分辨率低但时间分辨率高,适合捕捉高频细节;尺度大的时候,小波在时间上展宽,频率分辨率高但时间分辨率低,适合捕捉低频背景。
这个特性天然适配气象序列分析。降水和气温中既包含季节内尺度的波动,也有年际尺度的ENSO信号和年代际尺度的背景趋势,不同尺度信号叠加在一起。小波变换做的就是把这张混合信号按“尺度-时间”两维拆开,得到小波功率谱后,横轴是时间、纵轴是周期,颜色深浅代表功率强度,图像的局部高亮区域就是特定时段内某个周期信号增强的证据。比起傅里叶谱那条一维曲线,这个二维图谱信息量完全不是一个量级。
1.3 气象周期分析为什么首选连续小波变换和Morlet小波
小波变换分连续型和离散型两类。离散小波变换主要面向信号压缩和去噪,适合工程重构;气象要素的周期分析基本都用连续小波变换(CWT),因为它输出的是连续尺度上的功率谱,可以直接定位周期。而在众多母小波函数中,最常用的是Morlet小波——一个复值小波,由一个平面波乘高斯窗构成。它的优势在于尺度和周期之间有近似线性的对应关系,尤其在中心频率取6的时候,小波尺度s几乎就等于傅里叶周期,这极大方便了结果解读。
另一个常用干墨西哥帽小波(Mexican Hat),它响应的是信号的极值特征,对降水这类有尖峰突变的序列会产生较多的伪振荡,形态上也容易出多余的峰。我个人的建议是:除非你已经清楚知道需要探测信号的哪种形态特征,否则气象序列的周期分析直接选Morlet小波,参数选Torrence和Compo那套经典值就行,这也是目前气象文献里最主流的做法。
2. 从原始数据到功率谱图:完整流程与关键操作
2.1 数据预处理:缺测插值、去趋势、标准化
拿到资料不要直接丢进小波函数。第一步是检查时间序列的连续性和均匀采样。气象站的逐月资料偶尔会有缺测,小波变换要求等间隔采样,缺测的地方需要先用插值补上。长期缺测较多的站点建议先做插补或者直接筛掉,缺测过多的序列插值后会产生严重的低频伪信号,得不偿失。
第二步是去趋势。降水序列里如果有一条长期的线性或非线性趋势(比如城市化导致的局地降水增加),小波功率谱的低频段会出现一条高功率带,容易掩盖真正的年代际周期信号。通常做法是用线性回归或高通滤波去除趋势项,再用均值方差把序列标准化为标准正态序列。标准化这一步看起来不起眼,但很有必要:一方面让不同要素(降水和气温)之间的功率可比,另一方面显著性检验时背景谱的假设也建立在标准化序列上,不标准化会直接影响检验结果。
2.2 尺度参数设定:最小尺度、最大尺度、每倍频程子尺度数
连续小波变换里需要人为指定一组尺度去扫描信号,尺度范围设不对,结果要么漏掉目标周期,要么低频段出现大片无意义的高功率。气象分析里通常遵循Torrence和Compo的做法:最小尺度取2倍采样间隔(逐月资料就是2个月),最大尺度取序列长度的约1/3到1/2。如果序列长480个月,尺度上限设置在150~200个月附近比较合适,太大会产生大量不值得信任的边界效应。
每倍频程子尺度数(通常设为8~16)控制的是尺度轴的精细程度。设得越大,谱图越平滑,但计算量也线性增长。一般分析月尺度气候序列,设为8就够;如果图放大后感觉周期峰在尺度方向上没有足够的分辨率,再调到16。不要一上来就把所有尺度算满,浪费算力还容易让图显得花。
2.3 Python代码实现:基于常用库的完整示例
关于实现,我推荐先用现成库跑通流程。目前气象周期分析用得比较多的是Python里的pycwt库,它完全复现了Torrence和Compo方法,包含连续小波变换、显著性检验和绘图辅助函数。核心代码如下:
import numpy as np import pycwt as wavelet from pycwt.helpers import find_significant_peaks # data: 已预处理为标准化的一维 numpy 数组(逐月) # time: 对应的年月,如 np.arange(len(data)),单位“月” N = data.size dt = 1.0 # 采样间隔,逐月资料取1 # 定义尺度范围:最小2个月,最大约N/3个月 s0 = 2 * dt dj = 1.0 / 8 # 每倍频程8个子尺度 J = int(round(np.log2(N * dt / s0) / dj)) # 执行连续小波变换 mother = wavelet.Morlet(6) # 中心频率取6 wave, scales, freqs, coi, fft, fftfreqs = wavelet.cwt(data, dt, dj, s0, J, mother) # 计算小波功率谱和显著性水平 power = np.abs(wave) ** 2 signif, fft_theor = wavelet.significance(1.0, dt, scales, 0, 0.95, mother) signif = np.tile(signif, (N, 1)).T # 扩展到与power同维度 # 将红噪声显著性结果叠加在功率谱上 glbl_power = power.mean(axis=1) dof = N - scales glbl_signif, tmp = wavelet.significance(1.0, dt, scales, 1, 0.95, mother)这里几个参数的含义后面第3、第4节还会讲。plot部分可以直接用wavelet.contour,或者把power、scales、coi导出来在matplotlib里画,看个人习惯。注意输出结果里的coi就是影响锥(cone of influence),后面读图时千万不能忽视它。
2.4 如何读图:功率峰、闭合等值线与影响锥
小波功率谱图的三要素分别是等值线、阴影和影响锥。功率值超过红噪声95%显著性水平的区域,通常会画成黑线闭合的等值线圈或者加深的阴影区,这些才是能开口说“存在显著周期”的地方。看图时先找纵向连续的显著高功率区,再对应到纵轴的周期范围,就能读出具体是几年周期。
影响锥用半透明阴影标在图像两端,代表受边界填充影响的区域,这段区域内的功率值不可信。有一个常见的错误是拿着影响锥外缘的高功率区域就开始谈结论,实际上那很可能是零填充带来的边缘效应。真正稳妥的读图顺序是:先确认显著区域是否完全落在影响锥内部,再看它覆盖的时间范围和周期范围,最后才结合气候背景去解释。
3. 小波基和参数取舍——这里的选择直接决定结果好坏
3.1 Morlet小波的中心频率为什么常取6
Morlet小波由一个高斯包络和正弦波复合而成,中心频率ω0决定了高斯包络里能容纳多少个振荡周期。Torrence和Compo的经典配置取ω0=6,这个值被称为“尺度-周期等价”的关键点——当ω0=6时,小波尺度s和对应的傅里叶周期T近似满足T≈1.03s,基本可以认为尺度就是周期。如果ω0取小一些,比如取1或2,小波的时间分辨率变好,但频率分辨率变差,尺度到周期的换算关系也不再直接,读图时需要额外的换算步骤。
从实践角度说,气候周期分析最关心的是把年际、年代际周期清晰分层,ω0=6的频率分辨率足够把2年、4年、8年的峰分离开,不需要为追求极端时间分辨率去牺牲这个便利性。取更大的ω0(比如8以上)虽然频率分辨率更高,但对非平稳气候信号的时间局部特征捕捉变差,还会让边界附近的无效区域扩大。若非有特殊需求,就在标准配置附近做微调就好。
3.2 采样频率与周期范围的匹配问题
采样频率决定了你能探测的最短周期。逐月资料能可靠分辨的最短周期是2个月(奈奎斯特限制),所以尺度下限通常设为2。日资料则可以把尺度下限放到2天,能分析天气尺度和准两周振荡,而年资料就只能看年际以上的周期。这个匹配关系容易被新手忽略——拿着逐月降水资料想分析10天周期的干湿振荡,目标周期低于采样间隔两倍的极限,是不可能得到有效结果的。
另一方面,最大周期受数据长度限制。一个清晰的周期信号至少需要在序列中出现2~3个完整波形才能被识别。也就是说,要分析准20年周期的年代际信号,序列至少要有40到60年以上;只有30年资料,就别硬往20年以上的周期上解读。做实际项目时,这个限制要先在工作底稿里写明,避免后期被人质疑结论可靠性。
3.3 数据长度、尺度最大值的具体配置建议
我给一个经过多次验证的通用模板,适配绝大多数台站月资料分析场景:
- 采样间隔
dt = 1(月) - 最小尺度
s0 = 2(月) - 每倍频程子尺度数
dj = 1/8 - 尺度数量
J = int(np.log2(N / s0) / dj),其中N为月数 - 最大尺度自动就是
s0 * 2**(J*dj),约等于N/3个月
以480个月(40年)序列为例,尺度范围大约从2个月到160个月。这个配置下,2~4年的ENSO频段会有充足的分辨率,10年以上的年代际信号也能看到轮廓,但不建议对超过120个月的周期下强结论。如果需要重点分析年代际分量,可以在读图时把纵轴范围限定在5~15年重绘一次,比直接在原始谱里硬抠更清晰。
4. 显著性检验和边界效应:让结论经得起推敲
4.1 为什么用红噪声而不是白噪声做背景谱
气象要素序列通常不是白噪声,相邻月份之间存在显著自相关,这个性质在频谱上表现为低频段功率偏高,也就是所谓的“红噪声”。如果拿白噪声做背景去检验,低频段的功率很容易被误判为显著,得到一堆虚假周期。
小波功率谱的显著性检验标准做法是:先把原序列拟合成一个一阶自回归过程AR(1),得到滞后自相关系数α,再用这个α构造红噪声的理论功率谱作为零假设背景。计算方式是fft_theor = (1 - α²) / (1 + α² - 2α*cos(2π*scales*dt))(在标准化输入下),这一项就是检验的基准。pycwt库的significance函数里已经内置了这个逻辑,传入红噪声参数就能直接得到对应置信水平下的临界值。
4.2 蒙特卡洛检验作为补充方案
如果你觉得解析的红噪声假设不够稳妥,或者数据分布有明显特殊性,可以再用蒙特卡洛方法交叉验证。做法是:保持序列的AR(1)系数不变,生成几百组长度相同的人工红噪声序列,分别计算它们的小波功率谱,然后在每个尺度上取95%分位数作为显著性阈值。这个方法的道理是通过大量模拟直接构建统计分布,不依赖理论分布的近似假设。
我一般在正式图件里用理论红噪声检验,在方法验证时跑一次200~500组的蒙特卡洛,两者结论一致才会写进分析报告。需要提醒的是,蒙特卡洛对计算量有一定要求,几百组CWT跑下来时间不短,但考虑到结论的可靠性,这笔时间花得值。对于多发论文的场景,审稿人看到你用了交叉验证,说服力会提升不少。
4.3 影响锥的物理含义:为什么两端的结果不能信
小波变换在序列两端会遇到信号不足的问题,常见的处理方式是补零。补零后,落在边界附近的那些尺度较大的小波核,其一部分实际卷积的是人为填充的零值,计算得到的功率自然大幅衰减。为标记这片不可信区域,定义“影响锥”COI,表示小波功率因边界效应衰减到e-folding以下的区域。
需要注意,COI的范围不是固定的,它随尺度增大而扩大。大尺度的波核本身很宽,边界效应影响范围大;小尺度的波核窄,边界影响范围小。所以谱图的显著高功率区域哪怕整体偏向中间位置,也要检查它在每个尺度上是否都在COI内部。特别是当序列较短、目标周期较大时,整个有用频段可能都会被COI吞掉,这时只能老实承认“数据长度不足以支持该尺度上的结论”,换更长序列。
4.4 一次现实教训:忽略COI得出的“准20年周期”
多年前处理某站夏季降水资料时,统计得到一条30多年的序列,功率谱右上(低频端)有一段显著区域,当时粗略看了一眼它在COI附近,就直接写了准20年周期。后来换用更长序列复核,发现那个所谓20年周期在整段历史中根本没有稳定出现过,纯粹是补零和边界效应的产物。
自那以后,我的读图规则里加了一条硬性要求:凡是落在COI之外的轮廓线,一律不写进结论;即便在COI内有显著信号,也要设置一个最低持续时间(比如至少覆盖序列总长度的三分之一)才算有效周期。这个习惯帮我挡掉了不少后续审稿时的麻烦。
5. 一个完整案例:某站降水序列的小波功率谱分析
5.1 数据概况与预处理过程
举一个虚拟但贴近实际的案例。某站有1960—2000年逐月降水观测,共492个月(期间有3个月缺测)。预处理时先用自然邻域插值补缺,再对全序列做线性去趋势,最后减去均值除以标准差。小波分析参数采用上一节的标准模板,Morlet小波取ω0=6,尺度上限约150个月。
5.2 小波功率谱结果的解读路径
处理结果表明,整个时段内最突出的显著周期带位于2~4年(24~48个月),且没有覆盖全时段:在1960年代中期至1970年代中期、1980年代后期至1990年代初期两段信号较强,其余时段较弱,这提示该站降水年际变率可能与相关海域海温异常的位相变化存在不稳定的锁相关系。
另一个值得注意的特征是5~8年频段有零星的短时段显著信号,持续时长2~4年,但整体并非贯穿全程。由于它的显著区域基本落入COI边缘内,我对它持谨慎态度,结论只能写为“存在阶段性信号”,不能写成稳定的准周期。年代际尺度上(10年以上),该资料长度本身限制了判断力,谱图上虽然显示有一定功率聚集,但显著区域大部分在COI附近,因此不做强结论。
5.3 把周期信号翻译成气候物理意义
做周期分析的价值不在图本身,而在对图背后的物理机制给出合理解释。2~4年周期和ENSO准周期以及区域季风变率的耦合是常见组合;5~8年的信号需要结合局地海温和季节内振荡的年代际调制来分析;低频段可能存在与太平洋年代际振荡相关的背景信号。
我在做这类分析时还会做一个辅助工作:把显著周期段提取出来,做带通滤波后叠加原序列,直观对比“周期信号强时段”和“观测异常年份”的对位关系。这样既能验证周期分析是不是纸上谈兵,又能在汇报时给非专业听众一个直观的视觉结论,比单纯摆一张功率谱图有效得多。
6. 容易出错的地方与长期实操中的心得
6.1 去趋势不彻底导致的虚假低频信号
最常遇到的假象之一,是原始序列里带有缓慢的气候趋势或台站迁移造成的系统性偏移,这种趋势进入小波变换后会在低频段形成一片高功率带,看起来像存在一个漫长的周期信号,实际上只是趋势本身被小波基近似重构了。判别方法很简单:对比去趋势前后的功率谱图,如果去掉趋势后那个低频带随之消失,说明它不是真实周期。
6.2 显著性判断中的多重检验问题
做小波功率谱时,是对每个尺度、每个时间点同时做了多次显著性判断,严格来说天然伴随多重检验问题。几千次检验里总能找出几个侥幸过关的假阳性点,尤其功率谱图上布满杂散的“斑点”时更要注意。应对方法一是提高置信水平(比如取99%而非95%),二是要求显著区域在时间尺度上有连续性,而不是孤立点。从实践看,后者效果更为直观——真正成气候的周期信号不会只闪一下,而是形成条带状的显著区。
6.3 参数微调后的结果稳定性验证
审稿和自检时,一个常用技巧是微调关键参数,确认主要结论不随参数改变而漂移。比如把每倍频程子尺度数从8改成16、把最大尺度从N/3改成N/2,如果核心周期带的位置和范围基本不变,说明结果稳健;如果稍一改动谱图就面目全非,就要怀疑原始信号本身就不够强或数据里存在其他结构问题。这种方法成本低、说服力强,强烈建议每个人在最终提交前做一遍。
6.4 我的分析流程检查清单
在跑完pycwt并画好图之后,我会按以下顺序过一遍,确认没问题才采用结果:
- 序列是否连续等间隔采样,缺测是否已合理插补
- 是否做了去趋势和标准化
- 尺度范围是否匹配数据长度和分析目标
- 显著性检验是否使用了红噪声背景而非白噪声
- 读图时是否避开了COI区域
- 识别出的周期是否至少在序列中出现了2~3个完整波形
- 参数微调后核心结论是否仍然成立
这套流程走过一遍之后,小波功率谱得到的周期结论通常都比较经得起推敲。气象和水文序列的周期性分析,最难的地方不是算出那张图,而是不让错误的参数选择和边界伪影把你的注意力带偏。掌握了这些细节之后,再回头去看刚上手时画的那些谱图,多半会发现其中不少“显著周期”其实都站不住脚。这不算坏事,毕竟在数据分析这条路上,能发现自己的盲区,本身就是往前走了一大步。
本文还有配套的精品资源,点击获取