import os import pandas as pd import numpy as np import plotly.graph_objects as go from plotly.subplots import make_subplots import seaborn as sns import matplotlib.pyplot as plt from matplotlib.ticker import MultipleLocator from windrose import WindroseAxes from behavior.analyst import Analyst from utils.directoryUtil import DirectoryUtil as dir from algorithmContract.confBusiness import * from matplotlib.cm import get_cmap from matplotlib.colors import ListedColormap class WinRoseOfTurbineAnalyst(Analyst): """ 风电机组变桨-功率分析 """ def typeAnalyst(self): return "wind_rose_turbine" def turbinesAnalysis(self, dataFrameMerge, outputAnalysisDir, confData: ConfBusiness): self.windRoseAnalysis(dataFrameMerge, outputAnalysisDir, confData) def windRoseAnalysis(self, dataFrameMerge:pd.DataFrame, outputAnalysisDir, confData: ConfBusiness): # 检查所需列是否存在 required_columns = {confData.field_wind_dir,confData.field_wind_speed} if not required_columns.issubset(dataFrameMerge.columns): raise ValueError(f"DataFrame缺少必要的列。需要的列有: {required_columns}") # 风速区间 bins = [0, 3, 6, 9, np.inf] speed_labels = ['[0,3)', '[3,6)', '[6,9)', '>=9'] # 准备颜色映射 colors = plt.cm.Blues(np.linspace(0, 1, len(speed_labels))) cmap = ListedColormap(colors) # 将风向按照22.5度一个间隔进行分组 wind_directions = np.arange(0, 360, 22.5) # 按设备名分组数据 grouped = dataFrameMerge.groupby(Field_NameOfTurbine) print("self.ratedPower {}".format(confData.rated_power)) # 遍历每个设备并绘制图 for name, group in grouped: # 对风速进行分箱处理,但不添加到DataFrame中 speed_bins = pd.cut(group[confData.field_wind_speed], bins=bins, labels=speed_labels) # 将风向按照22.5度一个间隔进行分组 wind_directions = np.arange(0, 360, 22.5) group['风向分组'] = pd.cut(group[confData.field_wind_dir], bins=wind_directions, labels=wind_directions[:-1]) # 绘制风玫瑰图 fig, ax = plt.subplots(figsize=(8, 8), subplot_kw={'polar': True}) # 为每个风速区间绘制风向的条形图,并添加图例 for i, (label, color) in enumerate(zip(speed_labels, colors)): # 筛选出当前风速区间的数据 subset = group[speed_bins == label] # 计算每个风向分组的频数 counts = subset['风向分组'].value_counts().reindex(wind_directions[:-1], fill_value=0) # 绘制条形图,并添加标签用于图例 bar = ax.bar(counts.index * np.pi / 180, counts.values, color=cmap(i), alpha=0.75, width=(22.5 * np.pi / 180), label=label) # 设置标题和标签 ax.set_title(f"Wind Rose {name}", va='top') ax.set_theta_zero_location('N') # 设置0度位置为北 ax.set_theta_direction(-1) # 设置角度方向为顺时针 ax.set_yticklabels([]) # 不显示y轴刻度标签 ax.set_xticks(wind_directions * np.pi / 180) # 设置x轴刻度 ax.set_xticklabels(['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']) # 设置x轴刻度标签为方向 # 添加图例,并设置位置以避免与图形重叠 ax.legend(title='Wind Speed', bbox_to_anchor=(1.1, 1), loc='center left', borderaxespad=0.) # 保存图像并关闭绘图窗口 output_file = os.path.join(outputAnalysisDir, f"{name}.png") plt.savefig(output_file, bbox_inches='tight', dpi=120) plt.close()