☰
基于Matlab的测风塔数据处理与风能资源评估实战指南
2026/10/19 15:05:27 网站建设 项目流程

最近在处理某风电场前期选址的测风数据分析工作,突然觉得这类活儿挺值得拿出来讲讲。风能资源评估听着是个大词,落到具体执行层面,其实就是一件事:把气象塔(行业内常叫测风塔)测到的历史风力数据导入Matlab,完成清洗、预处理、统计分析,最终算出平均风速、威布尔分布参数、风功率密度、主导风向这些核心指标。这篇文章就围绕这个完整链路展开,适合刚接触风资源评估的工程师、相关专业的学生,以及对新能源数据分析感兴趣的人参考。我会把整个流程拆开讲,连踩过的坑一起交代。

1. 风能资源评估到底在算什么

测风塔的本质,是一个架在目标场址上的“长期气象观测站”。塔身上不同高度会安装风速计、风向标、温度探头和气压计,一般层高选10m、50m、70m、80m、100m这些典型风机轮毂高度附近。数据采集器通常每10分钟记录一次平均值,然后存成时间序列。这个10分钟的平均风速,就是后续所有分析的原始素材。

为什么必须依赖实测数据而不是气象站数据?因为风能资源评估要回答的是“本地风况到底适不适合发电”,而不是“这个地区大气候如何”。这两个问题的尺度完全不同。周边气象站的数据虽然年份长、容易拿,但海拔、地形粗糙度、山谷走向不一样,风况差异非常大。这也是测风塔数据不可替代的原因——它是场址真实风况的采样,精度和代表性都是模型再分析数据比不了的。

用Matlab来做这件事,有它非常实在的好处:读入CSV、Excel毫不需要额外写解析模块,统计工具箱自带威布尔拟合函数,绘图接口能出一整套风资源图表。对比Excel处理几十万行时间序列时的卡顿,Python虽然也能做但需要另配一套环境,Matlab在这个领域依然是很多设计院和咨询机构的首选工具。

整套评估链条有四个核心产出:长期平均风速和风切变指数、风速频率分布及威布尔拟合参数、风功率密度、主导风向与湍流强度。这四个指标直接决定了某个风机机型是否适配场址、排布间距怎么拉、理论发电量能到多少。所以后面所有代码,都是围绕这四个目标来组织的。

2. 气象塔数据的导入与格式处理

2.1 先弄清采集器导出的数据长什么样

测风塔的数据采集器多数支持直接导出CSV或TXT文件。以我常碰到的某项目X为例,导出文件的表头大致长这样:

时间戳风速70m风向70m风速50m风向50m温度气压
2019-01-01 00:007.822486.912526.2923.1
2019-01-01 00:108.152557.232496.3923.4
2019-01-01 00:207.572406.442386.1924.0

注意到几个细节:时间戳一般是字符串格式,风速单位是m/s,风向单位是度(0°表示正北,按顺时针增大,270°为正西),气压单位是hPa或kPa。有些采集器还会附加瞬时风速、最大风速或仪器状态码(比如9代表冻结、8代表校验失败),这些字段在清洗阶段非常有用,千万别一上来就删掉。

还有一个容易踩的坑:导出文件的编码。很多采集器软件在Windows下导出的是GBK编码,Matlab默认用UTF-8读会乱码。处理办法是提前用记事本之类工具另存为UTF-8,或者在读取时指定编码参数。

2.2 Matlab导入数据的三种方式

我最常用的方式是readtable,它能把CSV和TXT自动识别成表格变量,列名保留在变量名里,时间戳会被读成字符串或datetime,后续操作非常顺手。示例代码:

% 读取测风塔CSV文件 opts = detectImportOptions('wind_tower_data.csv'); opts.VariableNamingRule = 'preserve'; % 保留原始列名 data = readtable('wind_tower_data.csv', opts);

如果你手里的文件没有表头,只有纯数字矩阵,那就用readmatrix读取主体数据,同时单独把时间戳用readcell读进来拼接。这种方式适合那种导出了两年数据但前几行是采集器配置信息的老式格式。

第三种方式适合几十MB以上的大文件:用datastore创建数据流,按行迭代读取,避免一次性把全部数据压进内存导致卡顿。不过测风塔数据一般不会太大——10分钟间隔、全年数据也就52560条记录,Excel级别都已经能处理。真正要小心的是那种每秒钟存一次原始样本的采集器,数据量直奔百万行才需要考虑分块读取。

2.3 时间戳对齐和时区的坑

时间戳是整个数据集的锚点。如果时间轴没对齐,后面计算平均风速、日变化都会出错。常见的坑有三个:

第一个坑是时区。采集器默认记录UTC(协调世界时),但业务分析需要当地时间。中国地区的场址把UTC加8小时即可,但要注意很多老式采集器在转换时会把“UTC”写进时间戳导致datetime解析时自带时区偏移,最好是读进来以后统一用datetime的TimeZone属性处理,再转成无时区的本地时间。

第二个坑是夏令时和冬令时。国内不存在这个问题,但如果你处理的是境外项目,务必用datetime的自动转换特性,避免自己写加减小时逻辑,否则到了切换日必错。

第三个坑是缺失时间戳。采集器偶尔会因为停电、故障错过某个10分钟窗口,导致时间轴不连续。导入后第一件事就是检查时间间隔是否恒定:

time_diff = diff(data.timestamp); idx_gap = find(time_diff ~= minutes(10));

如果有不连续的位置,要把它们显式标出来,否则后面做傅里叶滤波、日均曲线时会造成假信号。我的习惯是直接在时间轴上生成完整的10分钟序列,用retime将原数据对齐到新的时间栅格上,缺失位置自然变成NaN,处理起来干净又明确。

3. 数据预处理:清洗决定了分析质量

3.1 有效数据完整率是第一道质量门槛

做风资源评估,第一件事不是急着算平均风速,而是先统计这一年数据到底“有效”了多少。行业里有个常用标准:月有效数据完整率不低于90%,年有效数据完整率不低于90%,否则这段时间的统计结果不具备代表性,需要补充测风。

有效数据指的是“未受仪器故障、覆冰、停机等因素影响”的数据。完整率计算公式很简单:

valid_ratio = sum(~isnan(data.ws_70m)) / height(data) * 100;

如果完整率低于90%,就需要排查是不是某几个月份仪器坏了。我处理过某项目X的数据,发现冬季两个月风速通道大量缺失,后来一查是风速计覆冰冻结,转不动了,这种情况不能简单插值补上,因为补出来的数据不代表真实风况,只能对缺失月份做标记,并在报告中说明。

3.2 缺失值处理:插值还是剔除

缺失值的去留取决于分析目的和缺失模式。如果缺失是零散的、孤立的,可以使用线性插值填上,对统计结果的影响很小。如果缺失是连续整段,比如连续3天没有数据,那就直接剔除这段,不做任何填充。

用Matlab补缺失值有两种推荐方式:

% 方式一:线性插值填充(适合零散缺失) data.ws_70m = fillmissing(data.ws_70m, 'linear'); % 方式二:用前后12小时的中位数平滑填充(适合小时级短段缺失) data.ws_70m = fillmissing(data.ws_70m, 'movmedian', hours(24));

强调一下,千万别对长期缺失段用插值。我曾经见过有人把连续一个月缺失段用线性插值补出来,结果算出来的年平均风速比真实情况偏低了将近10%,整个发电量估算都被带偏。连续缺失段必须通过完整率扣减的方式处理,或者在统计分析里直接屏蔽该类时段。

3.3 异常值识别:剔除有物理依据的坏点

异常值检测不能只靠肉眼扫散点图,要有物理依据。我一般按五个规则逐层过滤:

第一,风速不能为负,当风速等于0但风向正常时,大概率是风速计停转或冻住,要剔除。

第二,风速超出物理上限。虽然理论上强风可以超过60m/s,但测风塔风速计的量程一般也就50m/s,超出量程的读数必然是失真值,直接剔除。

第三,风向必须在0~360°范围内,超出范围的要么是传感器故障,要么是记录错误。

第四,垂直层之间做一致性检查。比如70m风速和50m风速在同一时刻的比值,正常情况下在1.0~1.3之间浮动(风切变导致高处风速更大),如果出现70m风速突然比50m低一大截,多半是仪器受到扰动,要检查原始记录。

第五,相邻时间段变化率检查。10分钟内风速突变超过20m/s基本不现实,超过的属于异常波动,需要标记。

这些规则写成Matlab脚本,逐条应用,最后生成一个质量标记列,完整保留原始数据,但又能在统计时快速过滤。我一直强调不要在原表上直接删行,这样会丢失溯源能力,后期复查时很难交代。

3.4 风向和风速的相关性校验

有一个容易被忽略的细节:风向传感器和风速传感器虽然在同一个支架上,但它们各自独立,可能其中一个坏了另一个还正常。如果发现风向全部指向同一方向或风速正常但风向乱跳,先用圆形直方图看一下风向分布是否合理。如果主导风向不在该地区的典型风向上,就要怀疑传感器是否装反或者数据记录通道接反。

还可以做风速风向的联合相关性检查,比如把风速按风向分扇区,统计各扇区的平均风速。正常情况下相邻扇区平均风速应该平滑过渡,如果某个扇区的平均风速突然离谱地高于周围扇区,大概率是局部流场受到塔影效应或者传感器支架干扰,这类数据在计算风玫瑰图时需要剔除对应风向区间,或者用其他高度层的数据交叉验证后决定是否保留。

4. 核心指标计算与统计建模

4.1 平均风速、风速日变化与风切变指数

平均风速是风资源评估最基本的指标。但直接对所有原始数据求算术平均并不严谨,应该以10分钟平均风速为样本,先按月按月求平均,再按年加权平均,这样能消除采样月份不均的影响。

风速日变化和季节变化同样重要。白天和夜间的风速可能存在显著差异,尤其是在复杂地形区域。用Matlab对多年数据做逐时刻平均,可以得到一条“平均日风速曲线”,这条曲线对风功率预测很有参考价值。

风切变指数描述风速随高度变化的规律。多数情况下风速随高度近似遵循幂律:

% 计算风切变指数 alpha h1 = 50; h2 = 70; v1 = nanmean(data.ws_50m); v2 = nanmean(data.ws_70m); alpha = log(v2/v1) / log(h2/h1);

alpha通常在0.1到0.3之间。如果某个高度层的alpha异常偏大或偏小,就要对该高度层的数据质量做进一步检查。这个指数在风机轮毂高度外推时非常关键——测风塔不一定刚好建到风机轮毂高度,但评估时要利用已有高度层的风速推算出轮毂高度的风资源。

4.2 威布尔分布拟合:风速频率分布的核心建模

风资源评估中最经典的分布模型是双参数威布尔分布。概率密度函数为:

f(v) = (k/c)·(v/c)^(k-1)·exp(-(v/c)^k)

其中k是形状参数,c是尺度参数。k值越大说明风速分布越集中,接近常数风;c值近似对应平均风速的水平。

拟合威布尔分布有两种常用方法:极大似然估计(MLE)和最小二乘法(LS)。Matlab里直接调用wblfit函数就能完成MLE拟合:

% 拟合威布尔分布参数(MLE法) ws = data.ws_70m(~isnan(data.ws_70m)); % 剔除缺失值 [parmHat, parmCI] = wblfit(ws); k = parmHat(1); % 形状参数 c = parmHat(2); % 尺度参数

拟合后要画频率直方图叠加拟合曲线,直观评估拟合效果。同时可以算拟合优度,比如将风速区间分成若干桶,比较每个桶的实际频率和理论频率,计算决定系数R²。通常情况下R²大于0.95就算是比较好的拟合。

如果拟合效果不理想,常见原因是数据里混入了异常时段或风速双峰分布。双峰分布常见于存在明显海陆风交替的地区,这时候需要做混合威布尔拟合或者分风向扇区分别拟合,不能拿单一分布硬套。

4.3 风功率密度:真正决定资源等级的量

平均风速高不代表资源一定好,因为风功率与风速立方成正比,风速的波动对能量贡献极大。风功率密度的公式是:

W/m² = 0.5·ρ·v³

其中ρ是空气密度,取1.225 kg/m³。用实测风速序列逐条计算再平均,得到的是实测风功率密度;用威布尔参数也能算理论风功率密度:

W/m² = 0.5·ρ·c³·Γ(1+3/k)

其中Γ是伽马函数。对比实测值和理论值可以校验拟合好坏。

在Matlab里计算实测风功率密度很直接:

rho = 1.225; % 海平面标准空气密度 power_density = 0.5 * rho * data.ws_70m.^3; mean_power_density = nanmean(power_density);

按国内风资源等级划分,50m高度年平均风功率密度大于400W/m²基本具备较好开发条件,300~400W/m²属于可开发但经济性一般,低于200W/m²基本不适合大规模风电开发。

4.4 风向玫瑰图与扇区统计分析

风向玫瑰图是风资源报告中最直观的一张图。它把360°划分成16个或12个扇区,统计各扇区的风频和平均风速。Matlab里可以用polarhistogram直接绘制:

% 风向玫瑰图(频率分布) figure; polarhistogram(deg2rad(data.wd_70m), 16, 'FaceColor', 'blue', 'FaceAlpha', 0.5);

更有价值的是“风向风速联合玫瑰图”,每个扇区用不同颜色表示平均风速区间,这样能直观看出哪个方向的风既多又强。扇区统计分析还要计算每个扇区的威布尔参数、湍流强度,特别是主导风向扇区,这些数据直接用于风机排布:主导风方向上风机间距要拉大,减少尾流影响。

4.5 湍流强度与极端风况

湍流强度TI定义为风速标准差除以平均风速,是风机载荷计算的重要输入:

% 按扇区计算湍流强度 ws_std = movstd(ws, 3); % 3个采样点窗口 ws_mean = movmean(ws, 3); TI = ws_std ./ ws_mean;

通常TI低于0.1说明风况平稳,0.1~0.25属于中等湍流,超过0.25就属于高湍流区域,对风机的疲劳载荷分析要格外谨慎。复杂山地和切变强烈的近海区域,TI往往偏高,选址时不能只看平均风速。

极端风况分析包括年最大风速、极大风速和风向的最大变化率。这些数据用于确定风机的极限载荷工况,对塔筒和叶片的结构设计至关重要。从实测数据中提取年最大3s阵风风速和50年一遇极大风速,虽然Matlab做不了外推统计,但至少可以把实测极值完整提取出来供结构工程师使用。

5. 核心Matlab代码实现与逐段解读

5.1 完整导入和清洗流程

这节给出一个可以直接套用的模板。假设数据文件叫wind_data.csv,包含时间戳、70m风速/风向、50m风速/风向、温度、气压六列。

% 1. 导入 opts = detectImportOptions('wind_data.csv'); opts.VariableNamingRule = 'preserve'; data = readtable('wind_data.csv', opts); % 2. 时间戳解析 data.timestamp = datetime(data.timestamp, 'InputFormat', 'yyyy-MM-dd HH:mm:ss'); % 3. 生成完整时间基准 fullTime = (data.timestamp(1):minutes(10):data.timestamp(end))'; data = retime(table2timetable(data), fullTime, 'linear');

这里用retime把数据对齐到完整时间栅格上,缺失位置自动生成NaN。table2timetable是Matlab中推荐处理时间序列的方式,后续很多时间相关操作都比普通table方便。

5.2 异常值过滤函数

把前面说的物理过滤规则封装成一个函数,返回逻辑索引,方便后续统计:

function valid = filter_anomalies(ws, wd) valid = true(size(ws)); valid(ws < 0 | ws > 60) = false; % 风速范围 valid(wd < 0 | wd > 360) = false; % 风向范围 d = abs([NaN; diff(ws)]); valid(d > 20) = false; % 突变检查 end

调用时逐高度层过滤,生成质量标记列。这里要注意,过滤之后的有效数据量如果太少,统计结果会显著失真,所以第一步先看完整率再决定是否继续。

5.3 威布尔MLE拟合及可视化

function [k, c, R2] = fit_weibull(ws) ws = ws(~isnan(ws)); [parmHat, ~] = wblfit(ws); k = parmHat(1); c = parmHat(2); % 拟合优度计算 edges = 0:1:ceil(max(ws)); obs = histcounts(ws, edges, 'Normalization', 'probability'); mid = edges(1:end-1) + 0.5; theo = wblpdf(mid, k, c) * 1; % 积分宽度1m/s R2 = 1 - sum((obs - theo).^2) / sum((obs - mean(obs)).^2); end

这里必须注意直方图桶宽的设置。如果桶宽取0.5m/s,理论概率也要按对应宽度缩放,否则R²算出来会偏小。

5.4 风功率密度和扇区统计

把扇区统计做成一个表输出,每行对应一个扇区,列出平均风速、风功率密度、湍流强度、频率占比:

function stats = sector_stats(ws, wd) sectors = 0:22.5:360; % 16扇区 stats = table(); for i = 1:length(sectors)-1 idx = wd >= sectors(i) & wd < sectors(i+1); s_ws = ws(idx); stats.mean_ws(i) = mean(s_ws, 'omitnan'); stats.power_density(i) = 0.5 * 1.225 * mean(s_ws.^3, 'omitnan'); stats.freq(i) = sum(idx) / length(ws) * 100; stats.ti(i) = std(s_ws, 'omitnan') / mean(s_ws, 'omitnan'); end end

注意扇区边界处理,风向正好等于360°的情况要归入第一扇区,否则会漏掉正北方向的数据。代码里可以用取模运算处理。

5.5 生成项目报告图表

输出图一般至少四张:风速频率直方图+威布尔拟合曲线、风向玫瑰图、风功率密度日变化曲线、风切变指数垂直剖面图。前三张我们上面已经覆盖,风切变剖面图实现如下:

figure; heights = [10, 50, 70, 100]; mean_ws_by_height = [4.8, 6.9, 7.6, 8.2]; plot(mean_ws_by_height, heights, '-o', 'LineWidth', 1.5); xlabel('平均风速 (m/s)'); ylabel('高度 (m)'); title('风廓线'); % 根据实际需要可改英文 grid on;

这张图能直观看出风速随高度的变化趋势,配合alpha值一起放到报告里,能让审查工程师快速理解场址的风切变特征。

6. 常见问题排查与实操心得

6.1 时间戳解析报错

datetime解析失败最常见的原因是格式不匹配。很多采集器导出的时间戳中带有“T”字符,比如2019-01-01T00:00:00,这时需要指定InputFormat为'yyyy-MM-dd''T''HH:mm:ss'。还有一种情况是导出的时间秒数被省略了,yyyy-MM-dd HH:mm也能解析,但要小心不同行格式不一致导致的丢数据。

排查技巧:先unique一下时间戳列,查看实际字符格式再写解析规则,不要瞎猜。

6.2 威布尔拟合不收敛或结果怪异

wblfit偶尔对双峰分布数据拟合效果很差,表现为k值极小或c值异常偏大。这时候先做风速频率直方图,看数据是否真的接近单峰分布。如果明显双峰,建议分时段或分扇区拟合;如果数据含有大量零风速(静风期),拟合也会被拉偏,可以先剔除风速小于0.5m/s的数据再拟合,并在报告里注明剔除比例。

6.3 风向玫瑰图方向偏移

如果绘制出来的玫瑰图主导风向和已知的区域气候资料明显不符,优先检查风向传感器安装是否正对正北。很多塔在安装时由于磁偏角未修正,导致整体风向偏差几十度,直接用会造成扇区统计全部错位。处理办法是如果已知当地磁偏角,对风向序列统一减去该角度后再分析。

6.4 完整率超90%但结果不合理

这种情况最常见的原因是多个高度层数据来源不同步。比如70m通道是采集器A记录的,50m通道是采集器B记录后人工合并的,两条时间序列没对齐。务必检查合并后每一行是否同一时间点,必要时做插值重采样统一到同一时间基准。

6.5 关于实操工具链的一点个人经验

坦率说,Matlab在风资源分析里最大的优势是“开箱即用”,统计工具箱和绘图功能覆盖了90%的日常需求,不需要像Python那样安装一堆第三方库。但要注意版本差异——老版本没有timetable和retime接口,需要自己写循环处理时间序列。建议尽量用较新版本,能省很多工作量。

另外,建议每个分析过程都保留原始数据副本,所有清洗步骤用脚本串联而非手动在变量区操作。我自己的习惯是在脚本开头设置随机种子、保留所有中间变量为结构体,这样无论何时回头看,都能完整复现当初的分析过程。风资源评估报告的审查非常严格,数据溯源能力比计算本身更重要。

这块内容其实还可以继续往外延伸,比如把威布尔参数用于理论发电量估算、结合SCADA数据做机群尾流分析,甚至搭一个简单的风速预测模型。但核心基本功就是这个:数据进得来、洗得净、算得准、画得出。这个闭环练熟了,再上什么复杂算法都不慌。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询