基于Matlab的风能资源评估实战:气象塔测风数据处理与指标计算

基于Matlab的风能资源评估实战:气象塔测风数据处理与指标计算 风电项目前期一群人扛着设备在山上待几个月图的是什么就是那几十米高的气象塔上几个风速仪和风向标记录下来的每一秒数据。这些从气象塔实测来的历史风力数据是整个风能资源评估最原始、也最可靠的依据。后面无论是选机位、算发电量、还是做微观选址都得回到这份数据上来。这篇就用Matlab完整走一遍数据导入、清洗处理、逐项计算评估指标、出图出报告把风能资源评估的数据分析流程掰开揉碎讲清楚。项目需要的Matlab代码实现我会把关键段落贴出来并且讲明白每一步为什么要这样做。适合风电行业的工程师、高校做风能方向研究的学生以及想拿真实气象数据练手的数据分析从业者。1. 项目背景与风能资源评估到底在评估啥1.1 气象塔测风数据为什么是金标准搞风电的人都知道一句话测风塔数据是风电场设计的基石。别管你用的是中尺度再分析数据还是卫星反演数据最后都得拿气象塔实测数据来校验。因为气象塔是原位测量——传感器就立在拟建机位附近直接记录真实流过场址的空气动能。相比之下再分析数据是网格插值出来的空间分辨率一般是几公里到几十公里地形复杂一点偏差就大。气象塔常见配置是在10米、30米、50米、70米、80米、100米等高度层安装风速仪和风向标有些塔还会挂温度、气压、湿度传感器。采样方式一般是记录每10分钟的平均风速、极大风速、主导风向部分塔还会保存1秒或几秒的原始瞬时数据。这套观测体系遵循IEC 61400-12等国际标准测出来的数据是后续所有计算的基础。不过实测数据不等于干净数据。气象塔在野外风吹日晒仪器结冰、传感器故障、鸟类停留、塔影干扰都会让数据出现异常。如果跳过质量控制直接算出来的风功率密度和发电量预测偏差可能相当可观。所以整个Matlab流程里数据预处理占的精力远比最后的公式计算多。1.2 评估指标清单风速、风向、湍流、切变写代码之前先想清楚要算哪些指标。风能资源评估的指标大致可以分成五个维度。平均风速与风速频率分布包括年平均风速、月平均风速、日变化规律以及风速的区间分布直方图。威布尔分布参数整个风资源行业都用两参数威布尔分布来刻画风速概率密度形状参数k和尺度参数c就是核心成果。风功率密度也叫风能密度是单位扫风面积上的风功率计算公式是0.5乘空气密度乘风速三次方的平均值。风向玫瑰图统计各风向扇区的出现频率用于判断主导风向、排布机位和设计尾流模型。湍流强度与风切变指数湍流强度影响机组疲劳载荷风切变指数描述风速随高度的变化规律直接关系到轮毂高度风速的推算。这五类指标计算逻辑其实都很简单难的是把数据处理好。下面按流程走。2. 数据导入与预处理2.1 原始数据长什么样——常见气象站数据格式解析我接触过的测风数据格式五花八门最常见的还是CSV、TXT和Excel。虽然列名不完全一样但核心字段基本固定字段说明示例时间戳日期时间可能是10分钟间隔202203011030WS80m80米高度平均风速(m/s)7.85WD80m80米高度平均风向(°)265.3WS50m50米高度平均风速(m/s)6.92WD50m50米高度平均风向(°)260.1Temp环境温度(℃)14.2Pressure大气压力(hPa)982.5Humidity相对湿度(%)56.0部分气象站还会给出极大风速、最小风速、标准差等列。拿到数据后第一步不是急着跑模型而是打开文件整体看一眼——有几列、多少行、时间是否连续、有没有明显的大段空白。我习惯先用几个命令快速勘察数据结构% 查看文件信息 fileInfo dir(wind_data_2022.csv); fprintf(文件大小: %.2f MB\n, fileInfo.bytes/1024/1024); % 预览前5行 opts detectImportOptions(wind_data_2022.csv); previewData preview(wind_data_2022.csv, opts); disp(previewData);detectImportOptions可以自动识别列类型省去手动指定格式的麻烦。不过自动识别偶尔会翻车比如时间列被识别成文本风速列里混了几个NA导致整列变字符型。遇到这种情况我会直接手动指定opts detectImportOptions(wind_data_2022.csv); opts.VariableNames {Time, WS80m, WD80m, WS50m, WD50m, ... Temp, Pressure, Humidity}; opts.VariableTypes {datetime, double, double, double, ... double, double, double, double}; data readtable(wind_data_2022.csv, opts);气象塔数据的时间精度很关键时间戳一旦错位后面所有风速-风向的对应关系都会出问题。所以我读入之后会立刻检查时间间隔是不是均匀的10分钟dt diff(data.Time); uniqueDt unique(dt); disp(uniqueDt);正常情况下uniqueDt应该只有一个值比如10分钟。如果出现多个值说明存在缺测后面就要做时间轴对齐和插值处理。2.2 Matlab读取实测数据的三种常用方式实际处理气象塔数据时不同数据来源对应的读取方式不太一样。我用得最多的是这三类。readtable通用表格读取适合CSV、TXT、Excel。优点是列名、类型识别方便缺点是文件较大时速度偏慢。textscan适合超大文本文件速度快、内存占用低。缺点是列数多时配置繁琐。readmatrix适合纯数值矩阵对时间戳和字符列支持不好通常配合readtable或textscan使用。这里给一个textscan读取上G级别原始测风数据的模板气象塔一秒级原始数据经常是这个规模fid fopen(raw_1s_data.txt, r); % 假设格式: 年月日时分秒, 风速, 风向, 温度 C textscan(fid, %f %f %f %f %f %f %f %f, ... Delimiter, ,, HeaderLines, 1); fclose(fid); raw_table table(C{1}, C{2}, C{3}, C{4}, C{5}, C{6}, C{7}, C{8}, ... VariableNames, {Year,Month,Day,Hour,Minute,Second, ... WS,WD,Temp});读完之后要马上转成统一的datetime列方便后续按时间聚合。textscan读取时最烦的是某一行数据缺字段会导致整列错位。遇到这种情况优先回到原始文件检查而不是在代码里硬凑。2.3 缺失值、异常值、野点剔除策略这是整个流程里最能体现经验的部分。气象塔数据常见的异常类型有三类缺失、超范围、跳跃突变。缺失值的处理相对简单。先定位缺失位置再决定是剔除还是填补。评估类项目我的原则是连续缺失小于3小时用线性插值超过3小时干脆剔除该段不参与统计。因为长时间插值会平滑掉风速的真实波动人为降低湍流强度。% 定位缺失 missingIdx ismissing(data.WS80m); fprintf(风速缺失比例: %.2f%%\n, sum(missingIdx)/height(data)*100); % 短时缺失插值 data.WS80m fillmissing(data.WS80m, linear, SamplePoints, data.Time, ... MaxGap, hours(3));超范围异常比较暴力但有效。风速不会长期超过60m/s台风等极端事件除外风向只在0到360度之间温度在-50到60度之间。超出物理范围的直接置为缺失% 物理范围检查 data.WS80m(data.WS80m 0 | data.WS80m 60) NaN; data.WD80m(data.WD80m 0 | data.WD80m 360) NaN; data.Temp(data.Temp -50 | data.Temp 60) NaN;最考验功力的是野点剔除。所谓野点就是数值在物理范围内、但明显偏离正常变化规律的异常点。业界常用的一种方法是IEC推荐的三标准差规则结合相邻点突变检测。具体做法以每个点为中心取前后各20个点约3小时窗口计算窗口内均值和标准差若该点偏离均值超过3倍标准差则判定为野点。window 20; % 前后各20个点 threshold 3; % 3倍标准差 ws data.WS80m; outlierIdx false(length(ws), 1); for i window1 : length(ws)-window seg ws(i-window : iwindow); seg seg(~isnan(seg)); if isempty(seg), continue; end mu mean(seg); sd std(seg); if abs(ws(i) - mu) threshold * sd outlierIdx(i) true; end end注意这里不能直接用包含该点的窗口计算均值和标准差否则异常点会把统计量拉偏。严格做法是用该点前后窗口的数据来评估该点但那样计算量大一些。对10分钟平均数据来说前后各20点完全够用。野点判定后我一般不会直接删掉而是置为NaN然后在统计阶段统一处理这样保留了一份清洗前的完整备份后面回溯问题也方便。处理完数据记得做一次可视化复核。画一张全年风速时序散点图扫一眼有没有明显的眉毛形异常段这比任何统计指标都直观。3. 核心评估参数计算原理与Matlab实现3.1 平均风速与风速频率分布数据清洗干净后第一步就是算年、月、日的平均风速。这里有个细节平均风速要用小时平均后再求日均还是直接用原始10分钟数据求两种方式结果差异不大但行业惯例是先用10分钟数据求小时平均再由小时平均求日平均、月平均最后得到年平均。这样既平滑了短时脉动又能保留日变化特征。用Matlab求各月平均风速很简单配合groupsummary函数% 加一个月份列 data.Month month(data.Time); monthlyMean groupsummary(data, Month, mean, WS80m); disp(table(monthlyMean.Month, round(monthlyMean.mean_WS80m, 2), ... VariableNames, {Month, MeanWS}));风速频率分布是后续威布尔拟合的基础。用histogram统计各风速区间的出现频率一般以0.5m/s为区间宽度edges 0:0.5:40; figure; histogram(data.WS80m(~isnan(data.WS80m)), edges, ... Normalization, probability, FaceColor, [0.2 0.4 0.8]); xlabel(风速 (m/s)); ylabel(频率); title(风速频率分布直方图);这里的Normalization参数设为probability得到的就是频率而非频数。风速分布通常右偏峰值在平均风速附近偏左的位置右侧拖一条长尾。这条长尾在风能评估里非常重要因为能量和风速三次方成正比少数大风时段贡献的能量占比极高。3.2 威布尔分布拟合及参数估计风资源行业对风速概率分布的建模几乎统一用两参数威布尔分布。概率密度函数长这样f(v) (k/c) · (v/c)^(k-1) · exp(-(v/c)^k)其中v是风速k是形状参数决定分布形态c是尺度参数与平均风速相关。k值越大风速分布越集中k值越小风速波动越大。典型陆上风场的k值在1.5到3左右海上风场风速稳定k值偏高。拟合方法最常用的是最大似然估计。似然方程是k [Σ(v_i^k · ln v_i) / Σ(v_i^k) - Σ(ln v_i) / n]^(-1)c (Σ(v_i^k) / n)^(1/k)第一个方程需要迭代求解kMatlab里可以直接用wblfit或者自己写一个迭代循环。wblfit的用法% 剔除NaN后进行威布尔拟合 wsClean data.WS80m(~isnan(data.WS80m)); [parmhat, parmci] wblfit(wsClean); k parmhat(1); c parmhat(2); fprintf(形状参数 k %.3f\n, k); fprintf(尺度参数 c %.3f m/s\n, c);wblfit返回的是[k, c]置信区间在parmci里。如果你想自己实现MLE迭代加深理解可以这样写% 极大似然法求解威布尔参数 ws wsClean(:); k0 2.0; % 初始值 tolerance 1e-6; maxIter 100; k k0; for iter 1:maxIter sum_vk sum(ws.^k); sum_vk_ln sum((ws.^k) .* log(ws)); sum_ln sum(log(ws)); k_new 1 / (sum_vk_ln / sum_vk - sum_ln / length(ws)); if abs(k_new - k) tolerance k k_new; break; end k k_new; end c (sum(ws.^k) / length(ws))^(1/k);这个迭代公式收敛很快一般几十次就结束了。需要注意初始值k0不能太大取2左右一般都能收敛。拟合完成后把理论威布尔密度曲线叠加到直方图上直观检查拟合效果v 0:0.1:35; pdf_wbl wblpdf(v, c, k); % 注意Matlab的wblpdf参数顺序是(x, A, B) hold on; plot(v, pdf_wbl * 0.5, r-, LineWidth, 1.5);等一下这里有个细节点要留意。Matlab的wblpdf(x, A, B)A对应尺度参数cB对应形状参数k和wblfit的输出参数顺序恰好一致。但很多论文里习惯写成(k, c)自己封装函数时一定要弄清楚谁是谁不然画出来的曲线错得离谱。3.3 风功率密度计算风功率密度是整个评估里最核心的指标直接决定项目值不值得投。计算公式是WPD 0.5 · ρ · (1/n) · Σ v_i³其中ρ是空气密度v_i是每个时间点的风速。注意这里用的是风速三次方的平均不是平均风速的三次方。两者差距相当大——风速波动越大三次方平均比平均的三次方高出越多。这也是为什么稳定风场和湍流风场的发电潜力差别那么大。空气密度不能简单取1.225。理想气体状态方程给出的修正公式是ρ P / (R · T)其中P是大气压力PaR是气体常数287.05 J/(kg·K)T是开尔文温度。如果没有实测气压也可以用海拔和经验温度估算。实际项目中如果气象塔装有温度和气压传感器就用实测值逐点计算密度再代入% 逐点计算空气密度 T_kelvin data.Temp 273.15; P_pa data.Pressure * 100; % hPa转Pa rho P_pa ./ (287.05 * T_kelvin); % 计算风功率密度 ws_cube_mean mean(data.WS80m.^3, omitnan); WPD 0.5 * mean(rho, omitnan) * ws_cube_mean; fprintf(年平均风功率密度: %.2f W/m²\n, WPD);风功率密度的等级划分可以直接参考国标。一般来说WPD低于150W/m²属于较差风资源150到300属于一般300以上具备较好的开发价值。但实际判断还要结合湍流、极端风况和并网条件。3.4 风向玫瑰图与湍流强度分析风向玫瑰图在Matlab里的实现有多种方式。老版本用rose函数新版本推荐polarhistogram。核心是先把风向划分成16个扇区每个扇区22.5度统计各扇区风向出现频率再画成极坐标柱状图dirClean data.WD80m(~isnan(data.WD80m)); % 风向转弧度 dirRad deg2rad(dirClean); figure; polarhistogram(dirRad, 16, Normalization, probability); ax gca; ax.ThetaZeroLocation top; ax.ThetaDir clockwise; title(80m风向玫瑰图);把ThetaZeroLocation设为top、ThetaDir设为clockwise是因为气象学里的风向习惯是北为0度、顺时计增加这和数学极坐标的逆时针从东开始不一样。不调整的话画出来的玫瑰图方向是错的主导风向会偏90度。湍流强度是表征风速脉动剧烈程度的指标定义为风速标准差与平均风速之比TI σ / V计算时一般按10分钟数据、以小时为单位聚合% 先把数据按小时聚合 data.Hourly dateshift(data.Time, start, hour); hourly groupsummary(data, Hourly, {mean, std}, WS80m); ti hourly.std_WS80m ./ hourly.mean_WS80m; % 剔除平均风速过小的点 validTI ti(hourly.mean_WS80m 4); fprintf(平均湍流强度(4m/s): %.2f%%\n, mean(validTI)*100);注意湍流强度只在平均风速较高时才有意义。风速趋近于零时微小的风速波动都会导致TI值爆表这些点要剔除。行业惯例是只统计平均风速大于4m/s的数据段。4. 完整代码实现与结果解读4.1 主程序框架从读取到输出的流程把前面讲的模块串起来一个完整的风资源评估Matlab脚本大概分六个步骤读取配置、导入数据、质量控制、指标计算、绘图输出、导出报告。这个流程我整理成函数化结构方便复用。%% 主程序入口 clear; close all; clc; % 1. 读取文件 rawData loadWindData(wind_data_2022.csv); % 2. 质量控制 cleanData qcWindData(rawData); % 3. 计算评估指标 metrics calcWindMetrics(cleanData); % 4. 可视化 plotWindResults(cleanData, metrics); % 5. 导出报告 exportWindReport(metrics, wind_assessment_report.xlsx);每个功能独立封装成函数好处是换数据源时不用改动整个脚本。函数内细节前面已经讲过这里给一个完整的聚合计算函数示例function metrics calcWindMetrics(data) % 计算年平均风速 metrics.meanWS mean(data.WS80m, omitnan); % 威布尔拟合 wsClean data.WS80m(~isnan(data.WS80m)); parmhat wblfit(wsClean); metrics.k parmhat(1); metrics.c parmhat(2); % 风功率密度 T_kelvin data.Temp 273.15; P_pa data.Pressure * 100; rho P_pa ./ (287.05 * T_kelvin); metrics.WPD 0.5 * mean(rho, omitnan) * mean(wsClean.^3); % 湍流强度大于4m/s hourly groupsummary(data, Hourly, {mean, std}, WS80m); valid hourly.mean_WS80m 4; metrics.TI mean(hourly.std_WS80m(valid) ./ hourly.mean_WS80m(valid)); % 风切变指数 % 风廓线幂律公式 v2/v1 (z2/z1)^alpha v80 nanmean(data.WS80m); v50 nanmean(data.WS50m); metrics.alpha log(v80/v50) / log(80/50); end风切变指数alpha这里用的是两个高度层的平均风速反推。严格做法应该逐时计算alpha再取均值因为大气稳定度变化会让alpha在一天之内波动很大。逐时计算的方法alpha_hourly log(data.WS80m ./ data.WS50m) / log(80/50); alpha_hourly alpha_hourly(isfinite(alpha_hourly) data.WS50m 3); metrics.alpha_mean mean(alpha_hourly);注意这里同样要过滤低风速工况否则两个风速都趋近于零时风速比值的噪声会被对数无限放大。4.2 关键代码段逐行讲解主流程里最容易写错又最难排查的往往是数据清洗环节。给一个完善的质量控制函数示例逐段注释function cleanData qcWindData(raw) cleanData raw; % 第一步物理范围检查 % 风速0~60m/s风向0~360温度-50~60°C气压850~1100hPa windCols {WS80m, WS50m}; dirCols {WD80m, WD50m}; for i 1:length(windCols) col windCols{i}; cleanData.(col)(cleanData.(col) 0 | cleanData.(col) 60) NaN; end for i 1:length(dirCols) col dirCols{i}; cleanData.(col)(cleanData.(col) 0 | cleanData.(col) 360) NaN; end cleanData.Temp(cleanData.Temp -50 | cleanData.Temp 60) NaN; cleanData.Pressure(cleanData.Pressure 850 | cleanData.Pressure 1100) NaN; % 第二步突变检查 % 10分钟间隔的两点风速差不应超过15m/s for i 1:length(windCols) col windCols{i}; ws cleanData.(col); diffWS abs(diff(ws)); spikeIdx [false; diffWS 15]; % 再验证后一个点是否回落 spikeIdx2 [spikeIdx(2:end); false] [false; diffWS 15]; ws(spikeIdx) NaN; cleanData.(col) ws; end end突变检查的思路是10分钟平均风速在相邻两个时刻跳变超过15m/s基本不可能是大气过程更可能是传感器瞬时故障或信号干扰。把突变点置为NaN后后面插值会补上但插值后的数据在统计湍流时权重降低。4.3 结果可视化与报告输出评估报告的核心图表一般包括五张全年风速时序图、月平均风速柱状图、风速频率直方图叠加威布尔拟合曲线、风向玫瑰图、日风速变化箱线图。这些图全部输出成PNG或PDF编码方式如下function plotWindResults(data, metrics) fig figure(Position, [100 100 1400 900]); % 图1全年风速时序 subplot(2, 3, 1); plot(data.Time, data.WS80m, ., MarkerSize, 3); xlabel(时间); ylabel(风速 (m/s)); title(80m全年风速时序); grid on; % 图2月平均风速 subplot(2, 3, 2); data.Month month(data.Time); monthlyMean groupsummary(data, Month, mean, WS80m); bar(monthlyMean.Month, monthlyMean.mean_WS80m, FaceColor, [0.2 0.6 0.4]); xlabel(月份); ylabel(平均风速 (m/s)); title(月平均风速); % 图3风速频率威布尔拟合 subplot(2, 3, 3); wsClean data.WS80m(~isnan(data.WS80m)); edges 0:0.5:35; histogram(wsClean, edges, Normalization, probability, ... FaceColor, [0.8 0.4 0.2], EdgeColor, none); hold on; v 0:0.1:35; plot(v, wblpdf(v, metrics.c, metrics.k) * 0.5, b-, LineWidth, 2); xlabel(风速 (m/s)); ylabel(频率); title([威布尔拟合 (k num2str(metrics.k, %.2f) ... , c num2str(metrics.c, %.2f) )]); % 图4风向玫瑰图 subplot(2, 3, 4); dirClean data.WD80m(~isnan(data.WD80m)); polarhistogram(deg2rad(dirClean), 16, Normalization, probability); title(80m风向玫瑰图); % 图5日变化箱线图 subplot(2, 3, 5); data.Hour hour(data.Time); boxplot(data.WS80m, data.Hour); xlabel(小时); ylabel(风速 (m/s)); title(风速日变化); % 图6风功率密度月度分布 subplot(2, 3, 6); rho data.Pressure * 100 ./ (287.05 * (data.Temp 273.15)); data.MonthlyWPD 0.5 * rho .* data.WS80m.^3; monthlyWPD groupsummary(data, Month, mean, MonthlyWPD); bar(monthlyWPD.Month, monthlyWPD.mean_MonthlyWPD, FaceColor, [0.4 0.4 0.8]); xlabel(月份); ylabel(风功率密度 (W/m²)); title(月平均风功率密度); saveas(fig, wind_assessment_plots.png); end导出Excel报告可以用writetable或者writematrix。我把关键指标汇总成一张表再写一个sheet% 汇总结果表 summaryTable table({datestr(now, yyyy-mm-dd HH:MM)}, ... metrics.meanWS, metrics.k, metrics.c, ... metrics.WPD, metrics.TI * 100, metrics.alpha_mean, ... VariableNames, {评估时间, 平均风速m_s, 威布尔k, 威布尔c, ... 风功率密度W_m2, 湍流强度pct, 风切变指数}); writetable(summaryTable, wind_assessment_report.xlsx, ... Sheet, 指标汇总);5. 常见问题与排查技巧实录5.1 野点剔除时容易踩的坑野点剔除看似简单实际操作里坑不少。第一个坑是雪球效应。前面提到的三倍标准差法如果数据里本身就有大量野点这些野点会把标准差拉大导致阈值偏大真正的野点反而不容易被识别出来。解决办法是分两步走先用物理范围粗筛再用统计方法精筛。粗筛把明显不合物理规律的剔除掉标准差回到正常量级精筛才有效。第二个坑是塔影效应。气象塔本身会对气流产生扰动。当风向直接吹向安装风速仪的横臂方向时塔身会在下风向形成低速尾流区这个方向上的风速测量值会系统偏低。这种塔影数据不是野点但确实是有偏观测。许多专业测风软件会提供塔影修正功能Matlab实现也不复杂判断风向是否落在塔影扇区通常是横臂正对方向的左右30度范围内对该扇区的风速按经验比例修正或剔除。第三个坑是夜间低风速期。夜间大气层结稳定近地面风速低且变化微小这时标准差极小任何一个小的风速跳动都可能被判定为野点。我遇到过一个数据源夜间野点率比白天高三倍。处理办法是不要对全时段统一阈值可以分白天和夜间两套统计参数或者直接加上风速大于某一阈值才检查跳变的条件。5.2 威布尔拟合不收敛怎么处理wblfit不收敛的情况我遇到过几次主要分两类。一类是风速数据里0值太多或者接近0的极小值占比过高会导致似然函数的数值计算出现异常。解决办法是先设置一个下限比如只统计风速大于0.1m/s的数据。另一类是数据量不足或分布严重双峰。有些沿海场址受到海陆风影响风速分布会出现明显的双峰特征单一威布尔分布拟合效果很差k值和c值都会偏离真实情况。这种场景下可以考虑改用双峰威布尔混合分布或者退一步用非参数的核密度估计来刻画风速概率密度。在Matlab里核密度估计一行代码[f, xi] ksdensity(wsClean, Bandwidth, 0.3); plot(xi, f, k-, LineWidth, 1.5);核密度估计不涉及参数假设拟合结果忠实于数据本身。缺点是外推能力弱不能像威布尔参数那样用来推算不同高度或不同时段的风速分布。所以我的做法是正常场址用威布尔拟合异常分布时用核密度做交叉验证报告里说明两种方法的差异。5.3 数据时间戳错位的排查时间戳问题最隐蔽也最容易毁掉整个评估。常见问题包括数据采集器时钟漂移导致每天慢几分钟时区设置错误导致全部数据偏移几个小时跨月和跨年时日期格式混用导致排序错乱。排查时间错位有一个非常实用的办法用风速日变化曲线的平滑度来验证。如果时间戳正确逐小时平均风速的日变化曲线应该是平滑的如果时间戳错位风向或温度的日变化曲线会出现台阶或跳变。另一种更直接的验证方法是用日出日落特征——温度和气压的日波动总是和太阳辐射相关的如果温度最低点不在凌晨而在中午时间一定有问题。% 时间轴检查看小时平均温度的日变化 data.Hour hour(data.Time); hourlyTemp groupsummary(data, Hour, mean, Temp); bar(0:23, hourlyTemp.mean_Temp); xlabel(小时); ylabel(平均温度 (°C)); title(温度的日变化曲线);正常情况下温度最低值在凌晨5到6点最高值在下午14到15点。如果这条曲线形态异常就要回到原始数据检查时区和采集器设置。数据记录仪说明文档里的时间戳定义一定看清楚有的记录的是本地时间有的是UTC跨时区项目特别容易在这个环节出错。还有一个经验技巧拿到新数据后第一时间把时间列和风速列画成散点图横轴用一年肉眼看有没有断崖或平移。信息量远大于任何自动检测算法。6. 实操经验和一些补充想法文章写到这里核心流程已经完整了。最后再分享几个个人体会。第一做风能资源评估数据质量控制的时间要占总时间的一半以上。很多同学拿到数据直接跑平均风速和功率密度结果算出来和参考值差很多回头检查才发现是野点和缺失值没处理干净。前期多花时间在数据可视化上把所有异常都暴露出来后面计算才能放心。第二Matlab里每一步都保留中间结果。我习惯把清洗前后的数据分别存成.mat文件把每个阶段的统计量都打印出来。出了问题可以往前回溯定位哪一步引入的偏差。第三这个流程算出来的指标只是静态评估。真正做风电场设计还要把威布尔参数输入WAsP或WindPRO这类商业软件结合地形和粗糙度做风流场模拟才能得到每个机位的准确风速和发电量。Matlab在这个环节的价值在于快速处理、快速验证、批量分析把数据基础打牢。6.1 一个快速自查清单写代码的过程中我总结了几个自查点每次跑完数据都会过一遍检查项正常范围异常处理数据有效率 90%低于90%谨慎评估年平均风速5-12 m/s低于5m/s一般不具开发价值湍流强度0.08-0.25大于0.25需关注机组选型风切变指数0.0-0.5超过0.3注意轮毂高度选取威布尔k值1.2-3.5超出范围检查数据质量主导风向占比前两扇区合计 40%风向分散则尾流影响大这套自查表可以帮你在提交报告之前快速发现数据或计算层面的低级错误。6.2 后续扩展方向这次实现的是风资源评估的静态指标计算。往下延伸可以做基于时间序列的风速预测模型用ARIMA或LSTM预测未来几小时到几天的风速为风功率预测服务。也可以把多座气象塔的数据联合分析构建场址内的风速空间相关性模型用于机组排布优化。如果对这个项目里的代码封装、函数设计有什么想聊的欢迎在评论区交流。我后续也会整理一版更完整的Matlab工具箱把这套评估流程做成点击即用的GUI界面方便不熟悉代码的同事直接上手。