Files
wind_power_cal/docs/大于4行时保留数据.py
T
2026-07-14 09:10:06 +08:00

226 lines
9.7 KiB
Python
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.
import sys
print("Python 解释器路径:", sys.executable)
print("已安装的包路径:", sys.path)
import data
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from pathlib import Path
# ----------------------
# 配置参数
# ----------------------
RAW_DATA_PATH = Path(r'D:\经手项目\数据分析项目\哈萨克斯坦项目\CHUZHIBAO\T01\T01 原始数据.xlsx')
CLEANED_DATA_PATH = Path(r'D:\经手项目\数据分析项目\哈萨克斯坦项目\CHUZHIBAO\T01\T01cleaned_scada_data.xlsx')
#中间保存路径
AFTER_LIMIT_POWER_PATH = Path(r'D:\经手项目\数据分析项目\哈萨克斯坦项目\CHUZHIBAO\T01\T01after_limit_power_cleaning.xlsx')
AFTER_TIP_SPEED_PATH = Path(r'D:\经手项目\数据分析项目\哈萨克斯坦项目\CHUZHIBAO\T01\T01after_tip_speed_cleaning.xlsx')
AFTER_SPEED_POWER_PATH = Path(r'D:\经手项目\数据分析项目\哈萨克斯坦项目\CHUZHIBAO\T01\T01after_speed_power_cleaning.xlsx')
RESULT_TABLE_PATH = Path(r'F:\风速区间功率均值表.xlsx')
RESULT_PLOT_PATH = Path(r'F:\风速功率曲线.png')
RATED_POWER = 4800 # 额定功率
RATED_WIND_SPEED = 18# 额定风速
POWER_STEP = 5
WIND_SPEED_STEP = 0.25 # 风速区间步长
WIND_SPEED_CHANGE_THRESHOLD = 1
#TIME_THRESHOLD = pd.Timedelta(hours=2)
IQR_MULTIPLIER1 = 1.8
IQR_MULTIPLIER2 = 2
MINIMUM_GENERATOR_SPEED = 1
K = 0.9 # k值:删除小于k倍最小发电机转速的点
# ----------------------
# 工具函数:定义保存数据
def save_intermediate_data(data,file_path,step_name):
"""保存中间数据的专用函数,仅做保存"""
try:
if data.empty:
print(f"⚠️{step_name}为空,不保存")
return
#创建目录(如果不存在)
file_path.parent.mkdir(parents=True, exist_ok=True)
#保存数据
data.to_excel(file_path, index=False,engine='openpyxl')
print(f"✅ {step_name}已保存({len(data)}条)至:{file_path}")
except Exception as e:
print(f"❌ 保存{step_name}失败:{str(e)}")
# ----------------------
# 数据清洗函数
# ----------------------
def load_data(file_path):
try:
if not file_path.exists():
raise FileNotFoundError(f"文件不存在: {file_path}")
data = pd.read_excel(file_path, engine='openpyxl')
print(f"成功读取数据,共{len(data)}条记录")
return data
except Exception as e:
print(f"数据读取错误: {str(e)}")
return None
def clean_scada_data(raw_data):
if raw_data is None or raw_data.empty:
print("无数据可清洗")
return None
data = raw_data.copy()
# 1. 基础过滤:删除停机数据
initial_count = len(data)
data = data[data['平均有功功率'] > 0].copy()
#1.5 删除小于最小发电机转速的点
if not data.empty and '平均发电机转速' in data.columns:
# 计算阈值:k倍最小发电机转速
speed_threshold = K * MINIMUM_GENERATOR_SPEED
# 过滤数据
data = data[data['平均发电机转速'] >= speed_threshold].copy()
removed_count = initial_count - len(data)
print(f"发电机转速过滤后保留 {len(data)} 条数据(移除{removed_count}条低转速数据,阈值: {speed_threshold:.2f}")
initial_count = len(data)
# 2. 时间列处理
if '时间' not in data.columns:
print("警告:数据中未找到'时间'列,无法进行限功率点识别")
return data
data['时间'] = pd.to_datetime(data['时间'], errors='coerce')
time_invalid_count = data['时间'].isna().sum()
data = data.dropna(subset=['时间'])
print(f"时间处理后保留 {len(data)} 条数据(移除{time_invalid_count}条无效时间数据)")
# 3. 识别并移除限功率点
if not data.empty:
min_power = data['平均有功功率'].min()
power_intervals = np.arange(min_power, RATED_POWER, POWER_STEP)
limit_power_points = []
for interval in power_intervals:
mask = (data['平均有功功率'] >= interval) & (data['平均有功功率'] < interval + POWER_STEP)
interval_data = data[mask]
if interval_data.empty:
continue
grouped = interval_data.groupby(interval_data['时间'].dt.date)
for date, group in grouped:
group_sorted = group.sort_values('时间')
wind_speed_range = group_sorted['平均风速'].max()-group_sorted['平均风速'].min()
if wind_speed_range > WIND_SPEED_CHANGE_THRESHOLD:
limit_power_points.extend(group_sorted.index)
data = data.drop(limit_power_points,errors='ignore')
print(f"限功率识别后保留{len(data)}条数据(移除{len(limit_power_points)}条限功率数据)")
save_intermediate_data(data,AFTER_LIMIT_POWER_PATH,"限功率清洗后的数据")
# 4. 计算并清洗叶尖速比
if not data.empty and '平均风速' in data.columns :
data = data[data['平均风速'] > 0].copy()
print(f"移除风速为0的数据后保留 {len(data)} 条数据")
data['叶尖速比'] =data['平均发电机转速']*3.14*162*78*30/data['平均风速']
#data['叶尖速比']= data['叶轮转速']*100/data['平均风速']
if not data.empty:
wind_speed_min = data['平均风速'].min()
wind_speed_max = data['平均风速'].max()
wind_speed_intervals = np.arange(wind_speed_min, wind_speed_max, WIND_SPEED_STEP)
cleaned_data_list = []
for interval in wind_speed_intervals:
mask = (data['平均风速'] >= interval) & (data['平均风速'] < interval + WIND_SPEED_STEP)
interval_data = data[mask]
if len(interval_data) >= 4:
q1 = interval_data['叶尖速比'].quantile(0.25)
q3 = interval_data['叶尖速比'].quantile(0.75)
iqr = q3 - q1
lower = q1 - IQR_MULTIPLIER1 * iqr
upper = q3 + IQR_MULTIPLIER2 * iqr
interval_cleaned = interval_data[(interval_data['叶尖速比'] >= lower) &
(interval_data['叶尖速比'] <= upper)]
else:
interval_cleaned = interval_data
cleaned_data_list.append(interval_cleaned)
data = pd.concat(cleaned_data_list)
print(f"叶尖速比清洗后保留 {len(data)} 条数据")
save_intermediate_data(data,AFTER_TIP_SPEED_PATH,"叶尖速比清洗后的数据")
# 5. 风速-功率关系清洗
if not data.empty and '平均风速' in data.columns and '平均有功功率' in data.columns:
wind_speed_min = data['平均风速'].min()
wind_speed_max = data['平均风速'].max()
wind_speed_intervals = np.arange(wind_speed_min, wind_speed_max, WIND_SPEED_STEP)
final_cleaned_list = []
for interval in wind_speed_intervals:
mask = (data['平均风速'] >= interval) & (data['平均风速'] < interval + WIND_SPEED_STEP)
interval_data = data[mask]
if len(interval_data) >= 4:
q1 = interval_data['平均有功功率'].quantile(0.25)
q3 = interval_data['平均有功功率'].quantile(0.75)
iqr = q3 - q1
lower_limit = q1 - IQR_MULTIPLIER1 * iqr
upper_limit = q3 + IQR_MULTIPLIER2 * iqr
interval_cleaned = interval_data[(interval_data['平均有功功率'] >= lower_limit) &
(interval_data['平均有功功率'] <= upper_limit)]
else:
interval_cleaned = interval_data
final_cleaned_list.append(interval_cleaned)
data = pd.concat(final_cleaned_list)
print(f"风速-功率清洗后保留 {len(data)} 条数据")
save_intermediate_data(data, AFTER_SPEED_POWER_PATH, "风速功率清洗后的数据")
# 6. 高风速区二次过滤
#if not data.empty and '平均风速' in data.columns:
#high_wind_mask = data['平均风速'] >= RATED_WIND_SPEED
#high_wind_data = data[high_wind_mask]
#if len(high_wind_data) > 0:
#robust_mean = high_wind_data['平均有功功率'].median()
#high_wind_filtered = high_wind_data[
#(high_wind_data['平均有功功率'] >= robust_mean * 0.98) &
#(high_wind_data['平均有功功率'] <= robust_mean * 1.02)
#]
#low_wind_data = data[~high_wind_mask]
#data = pd.concat([low_wind_data, high_wind_filtered])
#print(f"高风速区二次过滤后保留 {len(data)} 条数据")
return data
# ----------------------
# 主程序:执行数据清洗并保存结果
# ----------------------
if __name__ == "__main__":
# 加载原始数据
raw_data = load_data(RAW_DATA_PATH)
# 清洗数据
cleaned_data = clean_scada_data(raw_data)
# 保存清洗后的数据到指定路径
if cleaned_data is not None and not cleaned_data.empty:
try:
# 创建保存目录(如果不存在)
CLEANED_DATA_PATH.parent.mkdir(parents=True, exist_ok=True)
# 保存为Excel文件
cleaned_data.to_excel(CLEANED_DATA_PATH, index=False, engine='openpyxl')
print(f"清洗后的数据已成功保存到: {CLEANED_DATA_PATH}")
except Exception as e:
print(f"保存数据时出错: {str(e)}")
else:
print("没有可保存的清洗后数据")