Files
wind_power_cal/docs/风机历史数据无效值清洗与功率计算设计.md
T
cloud ce58c35c34 优化: 增强高风速功率曲线清洗
- 自动估算每台风机平台功率和平台起始风速
- 增加高风速低功率、曲线残差和严格平台过滤
- 前端展示估算参数并更新接口与设计文档
2026-07-14 16:10:29 +08:00

448 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 风机历史数据无效值清洗与功率计算设计
## 背景与目标
当前 `docs/完整年数据/` 目录下保存了 16 台风机从 `2024-09-01 14:00:00``2025-09-01 14:00:00` 的历史数据。以 `01_2024-09-01_14-00-00-2025-09-01_14-00-00_风机历史数据.xls` 为例,文件为 10 分钟粒度历史数据,包含风速、发电机转速、桨叶角度和有功功率等字段。
本文档定义两类计算口径:
- 无效值清洗:从历史数据中剔除停机、无风、无功率、异常转速、异常风速、疑似限功率和统计离群点。
- 风机功率计算:直接使用实测 `有功功率(kW)` 作为时刻功率,并基于清洗后的数据计算风速-功率曲线和发电量。
## 数据输入
当前历史数据字段如下:
| 字段 | 单位 | 用途 |
| --- | --- | --- |
| 时间 | - | 数据时间戳,当前主要为 10 分钟间隔 |
| 风机编号 | - | 区分风机,如 `01#` |
| 风机限功率时间(s) | s | 累计类字段,不能直接用 `> 0` 判断当前是否限功率 |
| 变流器发电机转速(rpm) | rpm | 辅助判断运行状态和转速异常 |
| 发电机转速(rpm) | rpm | 判断是否发电、计算叶尖速比时使用 |
| 风速(m/s) | m/s | 风速分箱和功率曲线计算 |
| 当前桨叶角度(°) | ° | 辅助识别停机、顺桨、限功率或异常状态 |
| 有功功率(kW) | kW | 实测输出功率,作为风机时刻功率 |
## 设计原则
- 先清洗后计算,所有功率曲线、发电量、性能指标均基于清洗后的有效数据。
- 实测功率优先,已有 `有功功率(kW)` 时不使用理论风功率公式反推时刻功率。
- 清洗规则分层执行,基础无效值直接剔除,疑似限功率和统计离群点应可追溯标记。
- 每个风速区间必须输出样本数,样本不足的区间不能作为正式功率曲线点。
- 额定功率和平台起始风速优先从每台风机的清洗后数据中自动估算,不能写死为旧脚本中的 `4800``6700`
- 自动清洗以可解释规则为主,先不引入 DBSCAN、RANSAC 或机器学习依赖。
## 无效值清洗方案
### 1. 字段校验
读取每个 `.xls` 文件后,先检查必需字段:
```text
时间
风机编号
发电机转速(rpm)
风速(m/s)
当前桨叶角度(°)
有功功率(kW)
```
如果缺少 `有功功率(kW)``风速(m/s)`,该文件不能用于功率曲线计算。如果缺少 `发电机转速(rpm)``当前桨叶角度(°)`,仍可做基础风速-功率统计,但不能执行完整运行状态清洗。
### 2. 时间清洗
时间字段需转换为标准时间戳。以下数据应剔除或单独标记:
- 时间为空或无法解析。
- 同一风机同一时间重复记录。
- 时间倒序记录。
- 与前一条记录间隔明显异常的数据段。
当前数据主要为 10 分钟粒度。若用于发电量积分,建议对异常间隔单独处理,不要默认每条都是 10 分钟。
### 3. 基础有效发电点过滤
用于计算风速-功率曲线时,建议保留满足以下条件的数据:
```text
风速(m/s) > 0
有功功率(kW) > 0
发电机转速(rpm) > 1
```
说明:
- `有功功率(kW) = 0` 通常表示未发电、停机、待机或数据无效,不应参与功率曲线均值。
- `发电机转速(rpm) <= 1` 通常表示机组未处于正常发电转动状态。
- 风速为 0 或负数不符合功率曲线计算输入条件。
### 4. 物理边界过滤
按机型参数增加边界过滤:
| 指标 | 建议规则 | 说明 |
| --- | --- | --- |
| 风速 | `0 < 风速 <= 35` | 超出范围优先视为传感器或导出异常 |
| 有功功率 | `0 < 有功功率 <= 额定功率 * 1.10` | 保留少量超额定裕度,过高视为异常 |
| 发电机转速 | `0 < 转速 <= 最大允许转速 * 1.05` | 最大允许转速从机型配置获取 |
| 桨叶角度 | `-10 <= 桨叶角度 <= 95` | 极端负角度或过大角度需结合状态判断 |
当前 01 号文件最大有功功率约为 `3307 kW`,因此该机组额定功率应按约 `3300 kW` 级配置,不能使用旧脚本中的 `4800 kW``6700 kW`
### 5. 疑似限功率识别
`风机限功率时间(s)` 是累计时间类字段,当前文件中全量数据均大于 0,不能用 `风机限功率时间(s) > 0` 判断当前记录是否限功率。
建议使用相邻记录增量辅助判断:
```text
限功率时间增量 = 当前行 风机限功率时间(s) - 上一行 风机限功率时间(s)
```
疑似限功率点可按以下条件组合识别:
- 限功率时间增量大于 0。
- 风速较高,但有功功率长期低于同风速段正常中位功率。
- 相邻多个 10 分钟点功率接近同一平台值,但风速变化明显。
- 桨叶角度明显偏大,且功率未随风速增加。
建议先把疑似限功率数据标记为 `is_limited = true`,不要直接删除。计算正常功率曲线时排除;分析限功率损失时保留。
### 6. 叶尖速比异常过滤
如果需要使用叶尖速比辅助清洗,应采用标准公式,不建议沿用旧脚本中的硬编码乘法。
叶尖速比计算公式:
```text
叶轮转速(rpm) = 发电机转速(rpm) / 齿轮箱速比
叶尖速比 = 叶轮转速(rpm) * 2π / 60 * 叶轮半径(m) / 风速(m/s)
```
示例:
```text
lambda = generator_rpm / gearbox_ratio * 2π / 60 * rotor_radius / wind_speed
```
叶轮半径、齿轮箱速比必须来自机型配置。清洗时可按风速分箱,对每个风速区间内的叶尖速比使用 IQR 或 MAD 剔除离群点。
### 7. 风速-功率离群点过滤
按风速分箱后,对每个风速区间内的 `有功功率(kW)` 做统计过滤。
推荐分箱宽度:
```text
0.5 m/s
```
样本数规则:
| 区间样本数 | 处理方式 |
| --- | --- |
| `< 10` | 不剔除,但标记为样本不足,不参与正式曲线 |
| `10 - 29` | 可做宽松离群过滤,结果标记为低置信度 |
| `>= 30` | 执行正式离群过滤,可用于功率曲线 |
IQR 过滤规则:
```text
Q1 = 区间功率 25% 分位数
Q3 = 区间功率 75% 分位数
IQR = Q3 - Q1
下限 = Q1 - 1.5 * IQR
上限 = Q3 + 1.5 * IQR
保留 下限 <= 有功功率 <= 上限 的数据
```
高风速额定平台区建议额外处理。额定风速以上,功率应接近额定功率;如果出现大量高风速低功率点,应优先判断为限功率、停机、故障或弃风,不应简单参与正常功率曲线均值。
### 8. 自动额定参数估算
在完成基础清洗、限功率识别、叶尖速比 IQR 和风速-功率 IQR 后,系统按风机独立估算平台参数:
```text
estimated_rated_power = 高功率稳定区域的稳健平台功率
estimated_rated_wind_speed = 分箱中位功率首次达到 0.95 * estimated_rated_power 的风速
```
估算规则:
- 先取有功功率的高分位区域,使用该区域的中位数估算平台功率,避免单个尖峰影响。
- 再按 `0.5 m/s` 风速分箱计算中位功率曲线,寻找首次进入 `95%` 平台功率的风速。
- 若样本不足或无法形成平台,则回退到后端默认参数,并标记 `source = fallback`
- 响应中按风机返回 `estimated_params`,用于前端展示和人工复核。
### 9. 高风速平台区二次过滤
自动估算平台参数后,对额定平台区执行二次过滤:
```text
平台区 = 风速 >= estimated_rated_wind_speed
平台功率中位数 = median(平台区有功功率)
MAD_sigma = 1.4826 * MAD(平台区有功功率)
下限 = max(0.85 * estimated_rated_power, 平台功率中位数 - max(4 * MAD_sigma, 0.08 * 平台功率中位数))
```
平台区内低于下限的数据标记为:
```text
high_wind_low_power
```
该规则专门处理高风速区仍明显低于平台功率的散点,避免这些点拉低正式功率曲线。
### 10. 鲁棒曲线残差过滤
平台区二次过滤后,系统再构建一条分箱中位功率基准曲线:
```text
1. 按风速分箱计算中位功率。
2. 对每个散点按风速插值得到期望功率。
3. 计算残差 = 实测功率 - 期望功率。
4. 在每个风速段内使用 MAD 自适应阈值剔除异常残差。
```
被剔除的数据标记为:
```text
curve_residual_outlier
```
该规则用于补充单纯 IQR 的不足,特别是异常点数量较多导致四分位范围被拉宽的场景。
### 11. 严格额定平台过滤
对已经进入稳定额定平台的高风速段,再执行更严格的低功率过滤:
```text
严格平台区 = 风速 >= estimated_rated_wind_speed + 0.5
下限 = max(
0.92 * estimated_rated_power,
平台功率中位数 - max(2.5 * MAD_sigma, 0.04 * 平台功率中位数)
)
```
严格平台区内低于下限的数据标记为:
```text
rated_plateau_low_power
```
该规则只作用于平台区,不作用于爬坡过渡段,用于进一步清除额定风速后残留的偏低散点。
## 风机功率计算方案
### 1. 时刻功率
历史数据中已有实测功率字段,时刻功率直接取:
```text
风机时刻功率(kW) = 有功功率(kW)
```
不建议使用以下理论公式替代实测时刻功率:
```text
P = 0.5 * ρ * A * Cp * v^3
```
该公式适合估算风能理论功率或做性能分析,需要空气密度、叶轮扫掠面积和功率系数,不适合在已有实测有功功率时反算实际输出。
### 2. 风速-功率曲线
风速-功率曲线用于描述不同风速下机组的实测输出能力。计算步骤:
```text
1. 使用清洗后的有效发电点。
2. 按风速分箱,建议 0.5 m/s 一个区间。
3. 每个区间统计有功功率。
4. 输出平均功率、中位数功率、样本数、标准差和分位数。
5. 样本不足或疑似限功率区间只标记,不作为正式曲线点。
```
区间定义建议采用左开右闭:
```text
(区间起点, 区间终点]
```
例如:
```text
(3.75, 4.25] -> 风速中心 4.0 m/s
(4.25, 4.75] -> 风速中心 4.5 m/s
```
输出字段:
| 字段 | 说明 |
| --- | --- |
| 风机编号 | 当前风机 |
| 风速区间起点 | 左边界 |
| 风速区间终点 | 右边界 |
| 风速中心 | 区间中点 |
| 样本数 | 清洗后有效点数量 |
| 平均功率(kW) | 区间功率均值 |
| 中位数功率(kW) | 区间功率中位数 |
| 功率标准差(kW) | 区间功率离散程度 |
| P25功率(kW) | 25% 分位数 |
| P75功率(kW) | 75% 分位数 |
| 置信度 | 正常、低样本、样本不足、疑似限功率 |
### 3. 发电量计算
若需要计算年发电量,应对功率按时间积分。
若确认每条数据为 10 分钟间隔:
```text
单条发电量(kWh) = 有功功率(kW) * 10 / 60
总发电量(kWh) = 所有单条发电量求和
```
更稳妥的通用算法是使用相邻时间戳差值:
```text
时间间隔(h) = 下一条时间 - 当前时间
单条发电量(kWh) = 当前有功功率(kW) * 时间间隔(h)
```
时间间隔异常时建议标记,不直接参与年发电量统计,或按业务规则补齐。
### 4. 理论风功率和性能指标
如需评估风能利用效率,可额外计算理论风功率:
```text
扫掠面积 A = π * 叶轮半径^2
理论风功率(kW) = 0.5 * 空气密度 * A * 风速^3 / 1000
功率系数 Cp = 有功功率(kW) / 理论风功率(kW)
```
注意:
- 空气密度应使用温度、气压、湿度或场站海拔修正。
- Cp 只用于性能分析,不用于替代实测 `有功功率(kW)`
- Cp 超出合理范围时,应优先检查风速测量、空气密度、功率单位和数据清洗规则。
## 数据处理流程
```text
读取 XLS 文件
-> 字段校验
-> 时间解析与排序
-> 基础有效发电点过滤
-> 物理边界过滤
-> 标记疑似限功率
-> 可选:叶尖速比异常过滤
-> 风速-功率分箱离群过滤
-> 自动估算平台功率和平台起始风速
-> 高风速平台区二次过滤
-> 鲁棒曲线残差过滤
-> 严格额定平台过滤
-> 输出清洗后明细
-> 输出风速-功率曲线表
-> 输出功率曲线图
-> 可选:计算发电量和性能指标
```
## 参数配置建议
| 参数 | 建议默认值 | 说明 |
| --- | --- | --- |
| 风速分箱宽度 | `0.5 m/s` | 功率曲线统计常用粒度 |
| 最小正式样本数 | `30` | 低于该值标记低置信度 |
| 最小保留样本数 | `10` | 低于该值不参与正式曲线 |
| IQR 系数 | `1.5` | 常规离群点过滤 |
| 发电机最小转速 | `1 rpm` | 判断是否发电 |
| 功率上限 | `额定功率 * 1.10` | 防止异常高功率 |
| 风速上限 | `35 m/s` | 防止异常风速 |
| 平台功率下限 | `max(85%额定功率, MAD 自适应下限)` | 剔除高风速低功率异常 |
| 残差过滤下限 | `max(4*MAD_sigma, 10%额定功率)` | 剔除低于主曲线的异常点 |
| 残差过滤上限 | `max(4*MAD_sigma, 16%额定功率)` | 剔除高于主曲线的异常点 |
| 严格平台下限 | `max(92%额定功率, 2.5*MAD 自适应下限)` | 剔除平台区残留偏低点 |
机型配置建议包含:
```text
风机编号
额定功率(kW)
额定风速(m/s)
叶轮直径(m)
齿轮箱速比
最大允许发电机转速(rpm)
切入风速(m/s)
切出风速(m/s)
```
## 验证计划
### 脚本验证
- 读取 01 号风机文件,确认字段数量和字段名正确。
- 统计原始行数、有效发电点数量、剔除数量和剔除原因。
- 输出每个风速区间的样本数、平均功率和中位数功率。
- 检查空文件、缺字段文件、全无有效数据文件不会报错。
### 结果验证
- 功率曲线应随风速整体上升,并在额定风速附近进入平台。
- 01 号风机最大实测功率约 `3307 kW`,额定功率配置应与该量级一致。
- 高风速低功率点应被标记为疑似限功率、停机或异常,而不是直接拉低正式曲线。
- 高风速平台区的保留散点应集中在自动估算的平台功率附近。
- `filtered_points` 中应能看到 `high_wind_low_power``curve_residual_outlier``rated_plateau_low_power`
- 样本数不足的风速区间应在结果中明确标记。
### 人工复核
- 抽查被剔除的数据,确认不是正常发电点被误删。
- 抽查疑似限功率点,结合桨叶角度和限功率时间增量确认规则有效。
- 对比厂家功率曲线或历史报告,确认实测曲线形态合理。
## 风险与对策
| 风险 | 影响 | 对策 |
| --- | --- | --- |
| 额定功率配置错误 | 功率上限过滤和平台判断失真 | 按每台机组实测最大功率和机型资料确认 |
| 把累计限功率时间误当状态量 | 大量正常数据被误删 | 使用相邻增量和功率形态综合判断 |
| 分箱样本数过少 | 曲线点随机波动大 | 输出样本数和置信度,低样本不参与正式曲线 |
| 平台参数估算失败 | 高风速过滤失效或误判 | 回退默认值并在 `estimated_params.source` 中标记 |
| 高风速异常点占比过高 | 平台中位数被拉低 | 平台过滤后再用残差过滤补充识别 |
| 叶尖速比公式错误 | 清洗结果偏差 | 使用标准公式,并配置叶轮半径和齿轮箱速比 |
| 时间间隔异常 | 发电量计算偏差 | 使用相邻时间差,并对异常间隔标记 |
## 参考资料
- POT-DBSCAN 风功率数据预处理方法:https://www.techscience.com/energy/v118n3/41894/html
- Adaptive DBSCAN 功率曲线异常点清洗:https://pure.ewha.ac.kr/en/publications/a-study-on-wind-power-curve-modeling-using-adaptive-dbscan/
- RANSAC 自适应阈值风功率数据清洗:https://www.nature.com/articles/s41598-025-89177-9
- 基于图像形态学的功率曲线异常点识别:https://arxiv.org/abs/2307.08539
## 后续实施建议
建议将现有两个脚本整理为一个可配置处理流程:
```text
clean_wind_history.py
- 读取单台或多台风机历史数据
- 输出清洗后明细
- 输出风速-功率曲线统计表
- 输出功率曲线图
- 输出清洗摘要报告
```
同时保留每条数据的清洗标记字段,例如:
```text
is_valid_generation
is_out_of_physical_range
is_suspected_limited
is_power_outlier
invalid_reason
```
这样后续既能生成正式曲线,也能追溯每条数据为什么被保留或剔除。