yaw_miss_analysis_original.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import pandas as pd
  2. import configparser
  3. import numpy as np
  4. def calculate_yaw_error(filtered_data, wind_speed_range, wind_speed_step, wind_direct_step, cabin_temp_step):
  5. # 计算风向、机舱角度 分别和360取模运算
  6. filtered_data['风向'] = np.abs((filtered_data['风向'] % 360))
  7. filtered_data['机舱角度'] = np.abs((filtered_data['机舱角度'] % 360))
  8. # 计算偏航误差
  9. filtered_data['偏航误差'] = filtered_data['风向'] - filtered_data['机舱角度']
  10. # 定义风速和舱内温度的分组范围
  11. # wind_speed_bins = np.arange(wind_speed_range[0], wind_speed_range[1] + wind_speed_step, wind_speed_step)
  12. wind_speed_bins = np.arange(filtered_data['风速'].min(
  13. ), filtered_data['风速'].max() + wind_speed_step, wind_speed_step)
  14. wind_direct_bins = np.arange(filtered_data['风向'].min(
  15. ), filtered_data['风向'].max() + wind_direct_step, wind_direct_step)
  16. cabin_temp_bins = np.arange(filtered_data['舱内温度'].min(
  17. ), filtered_data['舱内温度'].max() + cabin_temp_step, cabin_temp_step)
  18. # 按风速和舱内温度分组
  19. grouped = filtered_data.groupby([pd.cut(filtered_data['风速'], wind_speed_bins),
  20. pd.cut(
  21. filtered_data['风向'], wind_direct_bins),
  22. pd.cut(filtered_data['舱内温度'], cabin_temp_bins)])
  23. # 从每个分组中找出有功功率最大的行
  24. max_power_rows = grouped.apply(lambda x: x[x['有功功率'] == x['有功功率'].max()])
  25. # 计算每个分组的偏航误差平均值
  26. yaw_error_avg = grouped['偏航误差'].mean().dropna()
  27. return grouped, max_power_rows, yaw_error_avg
  28. def calculate_yaw_error2(data, wind_speed_step, wind_direct_step, cabin_temp_step):
  29. # 按风速和舱内温度分组
  30. data['风向分组'] = np.floor(data['风向'] / wind_direct_step) * wind_direct_step
  31. data['风速分组'] = np.floor(data['风速'] / wind_speed_step) * wind_speed_step
  32. data['舱内温度分组'] = np.floor(data['舱内温度'] / cabin_temp_step) * cabin_temp_step
  33. # 计算每个分组的偏航误差平均值
  34. grouped = data.groupby(['风向分组', '风速分组', '舱内温度分组'])
  35. # 从每个分组中找出有功功率最大的行
  36. # grouped.apply(lambda x: x[x['有功功率'] == x['有功功率'].max()])
  37. idx = grouped["有功功率"].idxmax()
  38. max_power_rows = data.loc[idx]
  39. yaw_error_avg = grouped['偏航误差'].mean().dropna()
  40. return grouped, max_power_rows, yaw_error_avg
  41. def calculate_angle_deviations(array1, array2):
  42. """
  43. 计算两个相同长度角度数组中两两对应角度值的偏差。
  44. 结果限制在-90°到+90°之间,并保留两位小数。
  45. 参数:
  46. array1 (list): 第一个角度数组
  47. array2 (list): 第二个角度数组
  48. 返回:
  49. list: 两两对应角度的偏差列表
  50. """
  51. deviations = []
  52. for angle1, angle2 in zip(array1, array2):
  53. # 计算原始偏差
  54. deviation = angle1 - angle2
  55. # 调整偏差,使其位于-180°到+180°范围内
  56. if deviation == 0.0:
  57. deviation = 0.0
  58. else:
  59. deviation = (deviation + 180) % 360 - 180
  60. # 将偏差限制在-90°到+90°范围内
  61. if deviation > 90:
  62. deviation -= 180
  63. elif deviation < -90:
  64. deviation += 180
  65. # 保留两位小数
  66. deviations.append(round(deviation, 2))
  67. return deviations
  68. def recalculation(data):
  69. # 计算风向、机舱角度 分别和360取模运算
  70. data['风向'] = np.abs(data['风向'] % 360)
  71. data['机舱角度'] = np.abs(data['机舱角度'] % 360)
  72. # 计算偏航误差
  73. # data['偏航误差'] =np.where(data['风向'] < data['机舱角度'],
  74. # (data['风向'] - data['机舱角度'])%360,
  75. # -(data['风向'] - data['机舱角度']) )
  76. data['偏航误差'] = calculate_angle_deviations(
  77. data['风向'], data['机舱角度'])
  78. return data
  79. def load_data(file_path, encoding='utf-8'):
  80. """
  81. Filters data from a CSV file based on specified criteria.
  82. Parameters:
  83. file_path (str): Path to the CSV file.
  84. encoding (str): Character encoding of the CSV file. Default is 'utf-8'.
  85. Returns:
  86. pd.DataFrame: Filtered DataFrame.
  87. """
  88. # Load the data
  89. data = pd.read_csv(file_path, encoding=encoding)
  90. return data
  91. def filter_data(data, wind_speed_range, active_power_range):
  92. # Filter criteria:
  93. # 1. "风机状态" (wind turbine status) must be 5
  94. # 2. No empty (null) values in the row
  95. filtered_data = data[(data['风机状态'] == 5)
  96. & (data["风速"] >= wind_speed_range[0])
  97. & (data["风速"] <= wind_speed_range[1])
  98. & (data['有功功率'] > 20)
  99. & (data['有功功率'] >= active_power_range[0])
  100. & (data['有功功率'] <= active_power_range[1])].dropna()
  101. filtered_data["时间"] = pd.to_datetime(filtered_data['时间'])
  102. """
  103. # 将时间列转换为13位长整型(Unix时间戳)
  104. # Excel 13位长整型转为时间 公式: =TEXT((K2/1000+8*3600)/86400+70*365+19,"yyyy-mm-dd hh:mm:ss")
  105. filtered_data["时间Unix"] = filtered_data['时间'].astype('int64') // 10**6
  106. """
  107. # 将时间列转换为10位长整型(Unix时间戳)
  108. # Excel 10位长整型转为时间 公式: =TEXT((A1+8*3600)/86400+70*365+19,"yyyy-mm-dd hh:mm:ss")
  109. filtered_data["时间Unix"] = filtered_data['时间'].astype('int64') // 10**9
  110. return filtered_data
  111. def read_config(config_file):
  112. """
  113. Reads configuration settings from an INI file.
  114. Parameters:
  115. config_file (str): Path to the INI configuration file.
  116. Returns:
  117. dict: Configuration settings.
  118. """
  119. config = configparser.ConfigParser()
  120. config.read(config_file)
  121. return config['DEFAULT']
  122. # Example usage
  123. # Replace with your file path
  124. file_path = 'E:\WorkSpace\Resource\Manage\项目\大唐\风电机组功率曲线异常检测分析服务项目\收资\data_process\data_second_scada_test.csv'
  125. def main():
  126. config_settings = read_config('config.ini')
  127. encoding = config_settings.get('Encoding', 'utf-8')
  128. wind_direct_step = float(config_settings.get('WindDirectStep', '1'))
  129. wind_speed_range = [float(x) for x in config_settings.get(
  130. 'WindSpeedRange', '3, 20').split(',')]
  131. wind_speed_step = float(config_settings.get('WindSpeedStep', '0.1'))
  132. cabin_temp_step = float(config_settings.get('CabinTempStep', '0.5'))
  133. active_power_range = [float(x) for x in config_settings.get(
  134. 'ActivePowerRange', '21, 1500').split(',')]
  135. raw_data = load_data(file_path, encoding)
  136. data = filter_data(raw_data, wind_speed_range, active_power_range)
  137. data=recalculation(data)
  138. # grouped,max_power_rows,yaw_error_avg = calculate_yaw_error(data, wind_speed_range,wind_speed_step, wind_direct_step,cabin_temp_step)
  139. grouped, max_power_rows, yaw_error_avg = calculate_yaw_error2(
  140. data, wind_speed_step, wind_direct_step, cabin_temp_step)
  141. print(" grouped by 风速、风向、舱内温度 ")
  142. # 将分组对象转换回 DataFrame
  143. grouped_df = grouped.apply(lambda x: x)
  144. # grouped_df=grouped.reset_index(drop=True)
  145. grouped_df.to_csv("./output/yaw_miss_grouped.csv",
  146. index=False, encoding="ansi")
  147. print(" max power rows ")
  148. print(max_power_rows)
  149. max_power_rows.to_csv("./output/yaw_miss_max_power_rows.csv",
  150. index=False, encoding="ansi")
  151. print(" yaw error avg dataframe")
  152. print(yaw_error_avg)
  153. print(" yaw miss avg: " )
  154. # print(data.head())
  155. print (data["偏航误差"].mean())
  156. if __name__ == "__main__":
  157. main()