# 风机历史数据无效值清洗与功率计算设计 ## 背景与目标 当前 `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 ``` 这样后续既能生成正式曲线,也能追溯每条数据为什么被保留或剔除。