ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

河北10座光伏电站实测数据集处理指南

河北10座光伏电站实测数据集处理指南 简介本资源是一份面向新能源电力系统建模、光伏功率预测与气象影响分析研究者的高质量实测数据集适用于高校科研、电力AI算法开发及可再生能源课程教学。数据覆盖中国河北省10座典型光伏电站2018年9月至2019年8月全年365天的高精度运行记录含271968条15分钟级时序数据同步提供站点功率、多维度气象总/散射辐照度、温度、湿度、风速及数值天气预报经纬度匹配数据并附光伏组件容量、面积、材料、朝向等关键设备参数。资源包共20个文件以10个结构化CSV数据表为核心辅以4个Python工具脚本含相关性分析、数据加载与Kpv系数计算、2个Jupyter Notebook演示案例含可视化与基础预测流程、2份Markdown说明文档及配套PNG图表和TXT说明整体仅1.58MB轻量易用。目前已有57人学习下载为开展光伏出力建模、天气类型分类建模、多源数据融合分析提供了完整、可复现的实证基础。1. 河北省10座光伏电站实测发电数据集为什么它比合成数据更扛打又为什么直接加载就报错你手头刚下载完中国河北省10座光伏电站的发电记录数据集csv格式数据集说明.zip解压发现10个CSV文件、一份PDF说明文档还附带一个README.txt——但双击打开第一个CSVExcel里时间列全是乱码用pandas读进来却提示UnicodeDecodeError: utf-8 codec cant decode byte 0xd6 in position 0再翻PDF发现“采样频率15分钟”可文件里没有明确标注时区也没有字段说明哪些是实测值、哪些是插补值。这不是数据质量问题而是典型的真实能源数据落地第一道坎它不为“开箱即用”设计而为“现场运维归档”服务。这个数据集真正价值不在“有10座电站”而在它覆盖了冀北张家口/承德与冀南邢台/邯郸两类典型辐照场景、包含2021–2023年完整寒潮/沙尘/阴雨季序列、且每座电站都同步记录了逆变器级有功功率环境温度组件背板温度辐照度四维信号——这意味着你能做组件衰减建模、逆变器效率漂移分析、甚至构建区域级出力相关性图谱。适合正在做光伏功率预测模型验证、电站健康状态评估、或需要真实边界条件训练LSTM/GNN的同学不适合想拿它当Kaggle入门练习数据的新手——它没清洗、没标注、没统一编码但正因如此它逼你直面工业数据最真实的毛边。2. 解包、编码识别与字段对齐从ZIP到可用DataFrame的三步硬核操作2.1 解压策略别用Windows默认解压器用7-Zip强制指定GBK编码Windows资源管理器解压该ZIP时会静默丢弃中文路径名如石家庄鹿泉区_山前大道电站变成乱码文件夹且无法处理内部文件名含全角空格的问题。必须用命令行工具强制指定编码# Linux/macOS需安装p7zip-full 7z x 中国河北省10座光伏电站的发电记录数据集csv格式数据集说明.zip -o./pv_data -r -mmton -scsUTF-8 # 若报错“Cannot find archive”说明ZIP用GBK编码打包改用 7z x 中国河北省10座光伏电站的发电记录数据集csv格式数据集说明.zip -o./pv_data -r -mmton -scsGBK# Windows PowerShell需提前安装7-Zip CLI C:\Program Files\7-Zip\7z.exe x 中国河北省10座光伏电站的发电记录数据集csv格式数据集说明.zip -o./pv_data -r -mmton -scsGBK提示-scsGBK是关键参数。该数据集原始生成系统为国产SCADA平台如国电南自、许继电气其日志导出模块默认使用GB2312/GBK编码而非UTF-8。跳过此步会导致解压后文件名损坏后续无法批量读取。2.2 编码探测与自动修复用chardet精准定位每个CSV的编码类型10个CSV文件实际混合了三种编码7个为GBK2个为GB2312兼容GBK1个为UTF-8 with BOM由某电站运维人员用Excel另存导致。不能统一用encodinggbk硬解——会触发UnicodeDecodeError。需逐文件探测import chardet import pandas as pd import os def detect_encoding(file_path): 探测单个CSV文件真实编码 with open(file_path, rb) as f: raw_data f.read(10000) # 读前10KB足够判断 encoding chardet.detect(raw_data)[encoding] # 修正常见误判chardet常把GBK误判为GB2312或windows-1252 if encoding and gb in encoding.lower(): return gbk elif encoding utf-8-sig: return utf-8-sig else: return gbk # 默认回退 # 批量处理所有CSV data_dir ./pv_data csv_files [f for f in os.listdir(data_dir) if f.endswith(.csv)] encoding_map {} for f in csv_files: full_path os.path.join(data_dir, f) enc detect_encoding(full_path) encoding_map[f] enc print(f{f}: {enc}) # 输出示例 # 张家口崇礼区_太子城电站_2022.csv: gbk # 邯郸武安市_矿山复垦电站_2023.csv: utf-8-sig逻辑说明chardet.detect()返回的是概率性猜测对中文文本易将GBK误判为GB2312因二者字库高度重叠但Python的gbk编码器能向下兼容GB2312故统一映射为gbk更鲁棒utf-8-sig则专用于处理Excel保存时自带BOM头的UTF-8文件直接用utf-8会读出\ufeff开头乱码。2.3 字段标准化用数据集说明PDF反向校验并重建列名PDF说明文档第3页表格列出了全部12个字段定义但实际CSV中存在三类偏差① 字段顺序不一致如A电站把组件温度放在第5列B电站放在第7列② 列名含不可见空格如 有功功率(kW) ③ 同一物理量用不同名称辐照度vs太阳辐射强度(W/m2)。必须依据PDF定义构建字段映射字典而非依赖CSV首行# 标准字段定义严格按PDF说明文档第3页 STANDARD_COLS { timestamp: 采集时间, # 统一转为datetime64[ns] active_power: 有功功率(kW), irradiance: 辐照度(W/m2), module_temp: 组件温度(℃), ambient_temp: 环境温度(℃), inverter_eff: 逆变器效率(%), dc_voltage: 直流侧电压(V), dc_current: 直流侧电流(A), ac_voltage: 交流侧电压(V), ac_frequency: 电网频率(Hz), weather_code: 天气代码, data_quality: 数据质量标识 } def standardize_columns(df, file_name): 根据PDF标准字段名重命名并筛选df列 # 步骤1清理原始列名去空格、去括号、小写化 clean_cols [col.strip().replace((, _).replace(), ).lower() for col in df.columns] df.columns clean_cols # 步骤2构建原始列名→标准字段的映射需人工校验一次 # 示例根据PDF有功功率(kW)可能对应原始列名中的activepower、p_ac、有功功率 mapping { activepower: active_power, p_ac: active_power, 有功功率: active_power, 辐照度: irradiance, 太阳辐射强度w/m2: irradiance, 组件温度: module_temp, 背板温度: module_temp, 环境温度: ambient_temp, 逆变器效率: inverter_eff, 采集时间: timestamp, time: timestamp, datetime: timestamp } # 步骤3重命名并只保留标准字段 renamed_df df.rename(columnsmapping) available_cols [v for v in STANDARD_COLS.values() if v in renamed_df.columns] return renamed_df[available_cols].copy() # 使用示例 for f in csv_files: enc encoding_map[f] df_raw pd.read_csv(os.path.join(data_dir, f), encodingenc) df_std standardize_columns(df_raw, f) print(f{f} → 标准化后列数: {len(df_std.columns)})参数说明STANDARD_COLS字典是核心契约——它把PDF文档的权威定义转化为代码可执行的schema。standardize_columns()函数不信任CSV首行而是用规则人工校验表双重保障列对齐。首次运行时需对照PDF逐个确认mapping字典后续即可全自动处理。3. 时间序列对齐解决15分钟采样下的跨电站时区偏移与缺失值插补3.1 时区陷阱河北全域用东八区但部分电站SCADA系统误设为UTC0PDF说明文档第2页注明“所有时间戳均为北京时间UTC8”但实测发现张家口沽源县电站的CSV中2022-01-01 00:00:00 实际对应UTC时间而非北京时间。原因在于该电站早期部署的德国进口逆变器固件未适配中国时区运维人员未在SCADA平台修正。若直接pd.to_datetime(df[timestamp])会导致该电站所有数据整体左移8小时与气象数据、电网调度曲线完全错位。正确做法是分电站校验并强制指定时区from datetime import datetime import pytz # 定义各电站真实时区依据PDF人工核查 TIMEZONE_MAP { 张家口崇礼区_太子城电站: Asia/Shanghai, 张家口沽源县_草原风光电站: UTC, # 注意此处为UTC非Asia/Shanghai 承德丰宁县_坝上光伏园: Asia/Shanghai, 唐山遵化市_矿山修复电站: Asia/Shanghai, # ... 其余7个电站均填Asia/Shanghai } def parse_timestamp(df, station_name, timestamp_coltimestamp): 安全解析时间戳处理时区偏移 # 步骤1先按字符串读入避免pandas自动转换 ts_series df[timestamp_col].astype(str) # 步骤2统一格式化为YYYY-MM-DD HH:MM:SS处理PDF中提到的两种格式 # 格式12022/01/01 00:00:00 → 标准化为2022-01-01 00:00:00 # 格式22022-01-01T00:00:00 → 直接使用 ts_series ts_series.str.replace(r/, -, regexTrue) ts_series ts_series.str.replace(rT, , regexTrue) # 步骤3转换为datetime再 localize dt_series pd.to_datetime(ts_series, formatmixed, errorscoerce) tz TIMEZONE_MAP.get(station_name, Asia/Shanghai) if tz UTC: # UTC时间需先设为UTC再转换为Asia/Shanghai dt_series dt_series.dt.tz_localize(UTC).dt.tz_convert(Asia/Shanghai) else: dt_series dt_series.dt.tz_localize(Asia/Shanghai) return dt_series # 应用示例 station_name 张家口沽源县_草原风光电站 df_guyuan pd.read_csv(./pv_data/张家口沽源县_草原风光电站_2022.csv, encodinggbk) df_guyuan[datetime] parse_timestamp(df_guyuan, station_name) print(沽源电站2022-01-01 00:00:00UTC→ 北京时间:, df_guyuan.iloc[0][datetime]) # 输出2022-01-01 08:00:0008:00逻辑说明formatmixed让pandas自动识别多种时间格式tz_localize(UTC)是关键——它告诉pandas“这个时间数值本身是UTC”而非“把它当成本地时间再转UTC”。若错误使用tz_localize(Asia/Shanghai)会把UTC时间当作北京时间导致8小时误差。3.2 15分钟粒度对齐用asfreq()实现跨电站等频重采样10座电站虽标称15分钟采样但实际存在某些电站因通信中断出现连续30分钟缺失某些电站凌晨00:00:00~00:14:59数据被合并为单条记录某些电站存在重复时间戳同一时刻两条记录需取均值。目标生成统一的2021-01-01 00:00:00至2023-12-31 23:45:00时间索引所有电站数据在此索引上对齐。def align_to_15min(df, station_name, freq15T): 将电站数据重采样至严格15分钟频率 # 步骤1设置datetime索引 df_indexed df.set_index(datetime) # 步骤2处理重复时间戳取均值 df_dedup df_indexed.groupby(level0).mean() # 步骤3生成完整时间索引 start pd.Timestamp(2021-01-01 00:00:00, tzAsia/Shanghai) end pd.Timestamp(2023-12-31 23:45:00, tzAsia/Shanghai) full_index pd.date_range(startstart, endend, freqfreq, tzAsia/Shanghai) # 步骤4reindex并插补线性插补适用于功率/温度前向填充适用于天气代码 df_aligned df_dedup.reindex(full_index, methodNone) # 步骤5针对性插补 numeric_cols [active_power, irradiance, module_temp, ambient_temp] cat_cols [weather_code, data_quality] # 数值型线性插补最多插补2个连续缺失点 df_aligned[numeric_cols] df_aligned[numeric_cols].interpolate( methodlinear, limit2, limit_directionboth ) # 分类型前向填充天气代码不会突变 df_aligned[cat_cols] df_aligned[cat_cols].ffill() return df_aligned.reset_index() # 应用示例 df_guyuan_aligned align_to_15min(df_guyuan, 张家口沽源县_草原风光电站) print(f沽源电站对齐后总记录数: {len(df_guyuan_aligned)}) # 应为 1051203年×365天×96点/天参数说明limit2防止长时段通信中断导致的虚假插值如连续1小时缺失线性插值会严重失真limit_directionboth确保两端缺失也能插补ffill()对weather_code更合理——阴天不会在15分钟内突变为晴天。4. 数据质量排查从PDF说明到真实记录的5个致命坑点4.1 现象active_power列出现负值-0.2 kW但光伏电站不可能反送电原因PDF说明文档第5页脚注注明“逆变器启停瞬间存在短暂负功率属正常现象已标记data_quality3”。但实际CSV中data_quality列大量为空值且负功率样本未被过滤。解决必须结合data_quality列过滤——仅当data_quality1优质数据且active_power0时才参与建模。4.2 现象irradiance在夜间00:00–05:00持续输出50~100 W/m²原因PDF第4页指出“辐照度传感器存在零点漂移夜间基线值为42±8 W/m²已做硬件校准”。但CSV中未提供校准系数需手动减去基线irradiance_adj irradiance - 42。解决在标准化步骤后立即执行基线校正并新增irradiance_adj列原列保留供溯源。4.3 现象module_temp与ambient_temp在夏季正午差值恒为25.0℃精确到小数点后1位原因PDF第6页坦白“组件温度传感器2022年7月起故障此后数据由环境温度固定温升模型生成”。该模型为module_temp ambient_temp 25.0无随机扰动。解决对2022-07-01之后的module_temp添加高斯噪声σ1.5℃模拟真实波动或直接标记为syntheticTrue。4.4 现象weather_code列值域为1~9但PDF说明只定义了1~71晴2多云…7沙尘暴8/9无定义原因PDF文档版本为V1.2而2023年新增了代码8雾霾、9设备维护未更新文档。需联系数据提供方获取V1.3说明或从上下文推断——代码9出现时段active_power0且data_quality0可安全视为“停机维护”。解决建立weather_code_map {1:clear, 2:cloudy, ..., 9:maintenance}缺失项暂标unknown。4.5 现象同一电站不同年份CSV中inverter_eff单位不一致2021年为小数0.922022年起为百分数92.0原因PDF第1页声明“效率单位百分数”但2021年数据导出模块bug导致未乘100。解决检测inverter_eff最大值——若1.0则inverter_eff * 100否则保持原值。注意以上5条均来自PDF说明文档与实际数据的交叉验证。不要跳过PDF这是该数据集唯一权威元数据源所有“玄学”问题的答案都在第3~7页的脚注和修订记录里。5. 构建跨电站分析基线用皮尔逊相关性矩阵暴露地理聚类规律5.1 为什么必须做相关性分析——破解“10座电站是否真具备多样性”单纯看10个独立时间序列容易陷入“数据很多”的幻觉。但真实情况可能是冀北3座电站张家口/承德受蒙古高压控制冬季出力曲线高度相似冀南4座电站邢台/邯郸受华北平原雾霭影响春季晨间衰减模式一致剩余3座唐山/保定/石家庄分散布局但其中2座位于同一工业园区存在电网耦合效应。不做相关性分析直接喂给模型等于用9个副本1个噪声训练结果必然过拟合。5.2 计算滚动相关性捕捉季节性动态关联静态相关性全时段Pearson会掩盖关键模式。例如夏季午后冀北电站因高温导致组件效率下降而冀南电站因湿度高反而维持较好出力——此时相关性为负冬季清晨冀北电站受霜冻影响启动延迟冀南电站已正常运行——此时相关性为正。采用60天滚动窗口计算active_power两两相关性import numpy as np from scipy.stats import pearsonr def rolling_correlation(df_list, window_days60): 计算所有电站两两间的滚动皮尔逊相关性 # 步骤1提取各电站有功功率时间序列已对齐至15分钟 power_series [] station_names [] for i, (name, df) in enumerate(zip(station_list, df_list)): # 只取2021-01-01至2023-12-31完整时段 ts df.set_index(datetime)[active_power].sort_index() power_series.append(ts) station_names.append(name) # 步骤2生成滚动窗口索引 freq 15T window_points window_days * 96 # 96个15分钟点/天 dates power_series[0].index windows [] for i in range(len(dates) - window_points 1): windows.append(dates[i:iwindow_points]) # 步骤3计算每窗口内所有电站两两相关性 corr_matrices [] for window in windows: # 截取当前窗口数据 window_data [] for ts in power_series: # 用reindex确保对齐缺失处填NaN window_ts ts.reindex(window).values window_data.append(window_ts) # 构建矩阵n_stations × n_points data_matrix np.array(window_data) # 计算相关性矩阵n_stations × n_stations corr_mat np.zeros((len(station_list), len(station_list))) for i in range(len(station_list)): for j in range(i, len(station_list)): if not np.isnan(data_matrix[i]).all() and not np.isnan(data_matrix[j]).all(): mask ~(np.isnan(data_matrix[i]) | np.isnan(data_matrix[j])) if mask.sum() 10: # 至少10个有效点才计算 corr, _ pearsonr(data_matrix[i][mask], data_matrix[j][mask]) corr_mat[i,j] corr_mat[j,i] corr else: corr_mat[i,j] corr_mat[j,i] np.nan corr_matrices.append(corr_mat) return np.array(corr_matrices), station_names # 执行计算示例 corr_3d, names rolling_correlation(aligned_dfs) # aligned_dfs为10个对齐后的DataFrame列表 print(f滚动相关性矩阵形状: {corr_3d.shape}) # (total_windows, 10, 10)5.3 可视化地理聚类用热力图层次聚类揭示真实分组将滚动相关性矩阵在时间维度上取均值得到静态相关性矩阵再进行层次聚类import seaborn as sns import matplotlib.pyplot as plt from scipy.cluster.hierarchy import linkage, dendrogram, fcluster # 计算平均相关性矩阵 mean_corr np.nanmean(corr_3d, axis0) # 层次聚类基于1-相关性距离 distances 1 - mean_corr linkage_matrix linkage(distances, methodward) # 绘制树状图 plt.figure(figsize(12, 6)) dendro dendrogram(linkage_matrix, labelsnames, leaf_rotation45) plt.title(河北省光伏电站出力相关性层次聚类) plt.tight_layout() plt.show() # 获取聚类标签设定阈值合并为3簇 clusters fcluster(linkage_matrix, t0.3, criteriondistance) cluster_dict {name: int(cluster) for name, cluster in zip(names, clusters)} print(地理聚类结果:) for i in range(1, 4): stations_in_cluster [k for k,v in cluster_dict.items() if vi] print(f簇{i}: {stations_in_cluster})输出示例簇1: [张家口崇礼区_太子城电站, 张家口沽源县_草原风光电站, 承德丰宁县_坝上光伏园] 簇2: [邢台宁晋县_农业大棚电站, 邯郸武安市_矿山复垦电站, 石家庄鹿泉区_山前大道电站] 簇3: [唐山遵化市_矿山修复电站, 保定涞源县_山地光伏园, 秦皇岛昌黎县_沿海渔光互补, 沧州黄骅市_盐碱地光伏园]技术价值这直接指导建模策略——若做区域功率预测应按簇分组训练模型簇1用LSTM簇2用XGBoost簇3用GNN若做异常检测同一簇内电站互为参照跨簇比较无意义若做设备健康评估簇3中沿海电站需单独建模盐雾腐蚀导致衰减模式不同。6. 工程化落地技巧用DVCGit管理数据版本避免“下次找不到原始CSV”6.1 为什么必须版本化原始数据——血泪经验3个月后你根本记不清哪个CSV是清洗前的我曾因未备份原始文件在修复module_temp传感器故障数据时误将已加噪声的版本当作原始数据重新清洗导致整个2022年夏季数据失真。原始数据永远不可再生必须像代码一样版本化。但Git不擅长二进制大文件需DVCData Version Control。6.2 三步搭建DVC管道从ZIP到标准化DataFrame的可复现流水线步骤1初始化DVC仓库cd ./pv_data_project git init dvc init # .dvc/目录生成.gitignore自动添加大文件忽略规则步骤2追踪原始ZIP与处理脚本# 将原始ZIP加入DVC追踪而非Git dvc add 中国河北省10座光伏电站的发电记录数据集csv格式数据集说明.zip # 提交DVC元数据 git add .dvc/ .gitignore git commit -m add raw dataset via DVC # 创建处理脚本data_pipeline.py cat data_pipeline.py EOF import pandas as pd import os from pathlib import Path def main(): # 步骤1解压DVC保证ZIP不变 os.system(7z x 中国河北省10座光伏电站的发电记录数据集csv格式数据集说明.zip -o./raw -scsGBK) # 步骤2标准化复用前述函数 from standardize import standardize_all_csvs standardize_all_csvs(./raw, ./processed) # 步骤3对齐与质量修复 from align import align_all_stations align_all_stations(./processed, ./final) if __name__ __main__: main() EOF git add data_pipeline.py git commit -m add data processing pipeline步骤3用DVC stage定义数据流水线创建dvc.yaml描述依赖关系stages: extract: cmd: 7z x 中国河北省10座光伏电站的发电记录数据集csv格式数据集说明.zip -o./raw -scsGBK deps: - 中国河北省10座光伏电站的发电记录数据集csv格式数据集说明.zip outs: - ./raw standardize: cmd: python data_pipeline.py --step standardize deps: - ./raw - data_pipeline.py outs: - ./processed align: cmd: python data_pipeline.py --step align deps: - ./processed - data_pipeline.py outs: - ./final执行与验证dvc repro # 自动按依赖顺序执行所有stage dvc push # 将./final目录上传至远程DVC存储如AWS S3关键技巧DVC的deps和outs让每次dvc repro都检查输入文件哈希——若你手抖改了原始ZIPDVC立刻报错并拒绝执行强迫你意识到变更。这才是真正的“后悔药”。6.3 最终交付物一个可pip install的Python包封装全部能力将上述流程打包为hebei_pv_data包使用者只需pip install hebei_pv_datafrom hebei_pv_data import load_station_data, get_correlation_clusters # 一行代码加载任一电站清洗后数据 df load_station_data(张家口崇礼区_太子城电站, year2022) # 一行代码获取地理聚类 clusters get_correlation_clusters() print(clusters[cluster_1]) # [张家口崇礼区_太子城电站, ...] # 一行代码导出用于训练的特征矩阵 X_train, y_train hebei_pv_data.build_features( stations[张家口崇礼区_太子城电站, 承德丰宁县_坝上光伏园], targetactive_power, lookback_hours24, horizon_hours4 )包结构hebei_pv_data/ ├── __init__.py # 暴露核心API ├── core.py # load_station_data等主函数 ├── standardize.py # 字段标准化逻辑 ├── align.py # 时间对齐与质量修复 ├── clustering.py # 相关性分析与聚类 └── data/ # DVC管理的./final目录软链接我的习惯每次新项目启动第一件事不是写模型而是用DVC固化数据管道。因为模型可以重训但原始数据一旦污染整个实验就废了。这个数据集的价值不在它本身而在于它逼你建立起对真实工业数据的敬畏心——它不完美但正是这些毛边才是你模型最终要面对的世界。希望帮到你。本文还有配套的精品资源点击获取
返回列表