Bladeren bron

优化打标签功能

wzl 9 maanden geleden
bovenliggende
commit
e4b07d5e15

+ 96 - 124
etl/step/ClassIdentifier.py

@@ -13,11 +13,11 @@ class ClassIdentifier(object):
     分类标识 -1:停机 0:好点  1:欠发功率点;2:超发功率点;3:额定风速以上的超发功率点 4: 限电
     """
 
-    def __init__(self, wind_turbine_number=None, origin_df: DataFrame = None,
+    def __init__(self, wind_turbine_number="", origin_df: DataFrame = None,
                  wind_velocity='wind_velocity',
                  active_power='active_power',
                  pitch_angle_blade='pitch_angle_blade_1',
-                 rated_power=1500, cut_out_speed=3, file_path: str = None):
+                 rated_power=1500, cut_out_speed=20, file_path: str = None):
         """
         :param file_path: The file path of the input data.
         :param origin_df: The pandas DataFrame containing the input data.
@@ -40,7 +40,7 @@ class ClassIdentifier(object):
 
         if self.cut_out_speed is None:
             trans_print(cut_out_speed, "WARNING:cut_out_speed配置为空的")
-            self.cut_out_speed = 3
+            self.cut_out_speed = 20
 
         if file_path is None and origin_df is None:
             raise ValueError("Either file_path or origin_df should be provided.")
@@ -59,104 +59,101 @@ class ClassIdentifier(object):
         power_rated = np.ceil(power_max / 100) * 100
         v_cut_out = self.cut_out_speed
         # 网格法确定风速风向分区数量,功率方向分区数量,
-        power_num = int(np.ceil(power_rated / 25))  # 功率分区间隔25kW
-        velocity_num = int(np.ceil(v_cut_out / 0.25))  # 风速分区间隔0.25m/s
+        power_bin_count = int(np.ceil(power_rated / 25))  # 功率分区间隔25kW
+        velocity_bin_count = int(np.ceil(v_cut_out / 0.25))  # 风速分区间隔0.25m/s
 
         # 存储功率大于零的运行数据
-        dz_march = np.zeros([wind_and_power_df_count, 2], dtype=float)
-        n_counter1 = 0
+        power_gt_zero_array = np.zeros([wind_and_power_df_count, 2], dtype=float)
+        power_gt_zero_array_count = 0
         for i in range(wind_and_power_df_count):
             if self.df.loc[i, self.active_power] > 0:
-                dz_march[n_counter1, 0] = self.df.loc[i, self.wind_velocity]
-                dz_march[n_counter1, 1] = self.df.loc[i, self.active_power]
+                power_gt_zero_array[power_gt_zero_array_count, 0] = self.df.loc[i, self.wind_velocity]
+                power_gt_zero_array[power_gt_zero_array_count, 1] = self.df.loc[i, self.active_power]
 
-                n_counter1 = n_counter1 + 1
+                power_gt_zero_array_count = power_gt_zero_array_count + 1
 
         # 统计各网格落入的散点个数
-        x_box_number = np.ones([power_num, velocity_num], dtype=int)
+        x_box_number = np.zeros([power_bin_count, velocity_bin_count], dtype=int)
 
         n_which_p = -1
         n_which_v = -1
-        for i in range(n_counter1):
-            for m in range(power_num):
-                if m * 25 < dz_march[i, 1] <= (m + 1) * 25:
+        for i in range(power_gt_zero_array_count):
+            for m in range(power_bin_count):
+                if m * 25 < power_gt_zero_array[i, 1] <= (m + 1) * 25:
                     n_which_p = m
                     break
-            for n in range(velocity_num):
-                if ((n + 1) * 0.25 - 0.125) < dz_march[i, 0] <= ((n + 1) * 0.25 + 0.125):
+
+            # todo 风速不太懂为什么区间用  0.125 -  0.375 而不是 0 - 0.25 区间
+            for n in range(velocity_bin_count):
+                if (n * 0.25 + 0.125) < power_gt_zero_array[i, 0] <= ((n + 1) * 0.25 + 0.125):
                     n_which_v = n
                     break
 
             if n_which_p > -1 and n_which_v > -1:
                 x_box_number[n_which_p, n_which_v] = x_box_number[n_which_p, n_which_v] + 1
 
-        for m in range(power_num):
-            for n in range(velocity_num):
-                x_box_number[m, n] = x_box_number[m, n] - 1
-
         # 在功率方向将网格内散点绝对个数转换为相对百分比,备用
-        p_box_percent = np.zeros([power_num, velocity_num], dtype=float)
-        p_bin_sum = np.zeros(power_num, dtype=int)
+        power_box_percent = np.zeros([power_bin_count, velocity_bin_count], dtype=float)
 
-        for i in range(power_num):
-            for m in range(velocity_num):
-                p_bin_sum[i] = p_bin_sum[i] + x_box_number[i, m]
+        # 功率方向统计
+        power_bin_sum = np.zeros(power_bin_count, dtype=int)
 
-            for m in range(velocity_num):
-                if p_bin_sum[i] > 0:
-                    p_box_percent[i, m] = x_box_number[i, m] / p_bin_sum[i] * 100
+        for i in range(power_bin_count):
+            power_bin_sum[i] = sum(x_box_number[i, :])
+            # for m in range(velocity_bin_count):
+            #     power_bin_sum[i] = power_bin_sum[i] + x_box_number[i, m]
+
+            for m in range(velocity_bin_count):
+                if power_bin_sum[i] > 0:
+                    power_box_percent[i, m] = x_box_number[i, m] / power_bin_sum[i] * 100
 
         # 在风速方向将网格内散点绝对个数转换为相对百分比,备用
-        v_box_percent = np.zeros([power_num, velocity_num], dtype=float)
-        v_bin_sum = np.zeros(velocity_num, dtype=int)
+        v_box_percent = np.zeros([power_bin_count, velocity_bin_count], dtype=float)
+        v_bin_sum = np.zeros(velocity_bin_count, dtype=int)
 
-        for i in range(velocity_num):
-            for m in range(power_num):
-                v_bin_sum[i] = v_bin_sum[i] + x_box_number[m, i]
+        for i in range(velocity_bin_count):
+            v_bin_sum[i] = sum(x_box_number[:, i])
+            # for m in range(power_bin_count):
+            #     v_bin_sum[i] = v_bin_sum[i] + x_box_number[m, i]
 
-            for m in range(power_num):
+            for m in range(power_bin_count):
                 if v_bin_sum[i] > 0:
                     v_box_percent[m, i] = x_box_number[m, i] / v_bin_sum[i] * 100
 
         # 以水平功率带方向为准,分析每个水平功率带中,功率主带中心,即找百分比最大的网格位置。
-        p_box_max_index = np.zeros(power_num, dtype=int)  # 水平功率带最大网格位置索引
-        p_box_max_p = np.zeros(power_num, dtype=int)  # 水平功率带最大网格百分比
+        p_box_max_index = np.zeros(power_bin_count, dtype=int)  # 水平功率带最大网格位置索引
+        p_box_max_p = np.zeros(power_bin_count, dtype=int)  # 水平功率带最大网格百分比
 
-        for m in range(power_num):
+        for m in range(power_bin_count):
             # 确定每一水平功率带的最大网格位置索引即百分比值
-            p_box_max_p[m], p_box_max_index[m] = p_box_percent[m, :].max(), p_box_percent[m, :].argmax()
-
-        # 以垂直风速方向为准,分析每个垂直风速带中,功率主带中心,即找百分比最大的网格位置。
-        v_box_max_index = np.zeros(velocity_num, dtype=int)
-        v_box_max_v = np.zeros(velocity_num, dtype=int)
-
-        for m in range(velocity_num):
-            [v_box_max_v[m], v_box_max_index[m]] = v_box_percent[:, m].max(), v_box_percent[:, m].argmax()
+            p_box_max_p[m], p_box_max_index[m] = power_box_percent[m, :].max(), power_box_percent[m, :].argmax()
 
         # 切入风速特殊处理,如果切入风速过于偏右,向左拉回
+        # todo 为什么第一行数据的索引值 > 14个就要往左拉回,还有是不是不叫切入风速,这个是 落入这个区间功率最多的个数的索引值
         if p_box_max_index[0] > 14:
             p_box_max_index[0] = 9
 
         # 以水平功率带方向为基准,进行分析
-        dot_dense = np.zeros(power_num, dtype=int)  # 每一水平功率带的功率主带包含的网格数
-        dot_dense_left_right = np.zeros([power_num, 2], dtype=int)  # 存储每一水平功率带的功率主带以最大网格为中心,向向左,向右扩展的网格数
+        dot_dense_left_right = np.zeros([power_bin_count, 2], dtype=int)  # 存储每一水平功率带的功率主带以最大网格为中心,向向左,向右扩展的网格数
         dot_valve = 90  # 从中心向左右对称扩展网格的散点百分比和的阈值。
 
-        for i in range(power_num - 6):  # 从最下层水平功率带1开始,向上到第PNum-6个水平功率带(额定功率一下水平功率带),逐一分析
+        for i in range(power_bin_count - 6):  # 从最下层水平功率带1开始,向上到第PNum-6个水平功率带(额定功率一下水平功率带),逐一分析
             p_dot_dense_sum = p_box_max_p[i]  # 以中心最大水平功率带为基准,向左向右对称扩展网格,累加各网格散点百分比
             i_spread_right = 1
             i_spread_left = 1
             while p_dot_dense_sum < dot_valve:
 
-                if (p_box_max_index[i] + i_spread_right) < velocity_num - 1:
-                    p_dot_dense_sum = p_dot_dense_sum + p_box_percent[i, p_box_max_index[i] + i_spread_right]  # 向右侧扩展
+                if (p_box_max_index[i] + i_spread_right) < velocity_bin_count - 1:
+                    # 向右侧扩展
+                    p_dot_dense_sum = p_dot_dense_sum + power_box_percent[i, p_box_max_index[i] + i_spread_right]
                     i_spread_right = i_spread_right + 1
 
-                if (p_box_max_index[i] + i_spread_right) > velocity_num - 1:
+                if (p_box_max_index[i] + i_spread_right) > velocity_bin_count - 1:
                     break
 
                 if (p_box_max_index[i] - i_spread_left) > 0:
-                    p_dot_dense_sum = p_dot_dense_sum + p_box_percent[i, p_box_max_index[i] - i_spread_left]  # 向左侧扩展
+                    # 向左侧扩展
+                    p_dot_dense_sum = p_dot_dense_sum + power_box_percent[i, p_box_max_index[i] - i_spread_left]
                     i_spread_left = i_spread_left + 1
 
                 if (p_box_max_index[i] - i_spread_left) <= 0:
@@ -168,127 +165,101 @@ class ClassIdentifier(object):
 
             dot_dense_left_right[i, 0] = i_spread_left
             dot_dense_left_right[i, 1] = i_spread_right
-            dot_dense[i] = i_spread_left + i_spread_right + 1
-
-        # 各行功率主带右侧宽度的中位数最具有代表性
-        dot_dense_width_left = np.zeros([power_num - 6, 1], dtype=int)
-        for i in range(power_num - 6):
-            dot_dense_width_left[i] = dot_dense_left_right[i, 1]
 
-        main_band_right = np.median(dot_dense_width_left)
+        main_band_right = np.median(dot_dense_left_right[:, 1])
 
         # 散点向右显著延展分布的水平功率带为限功率水平带
-        power_limit = np.zeros([power_num, 1], dtype=int)  # 各水平功率带是否为限功率标识,==1:是;==0:不是
+        # 各水平功率带是否为限功率标识,==1:是;==0:不是
+        power_limit = np.zeros([power_bin_count, 1], dtype=int)
         width_average = 0  # 功率主带平均宽度
-        width_var = 0  # 功率主带方差
-        # power_limit_valve = 6    #限功率主带判别阈值
-        power_limit_valve = np.ceil(main_band_right) + 3  # 限功率主带判别阈值
 
-        n_counter_limit = 0
+        # todo 限功率主带判别阈值为什么要加3
+        power_limit_valve = np.ceil(main_band_right) + 3  # 限功率主带判别阈值
         n_counter = 0
 
-        for i in range(power_num - 6):
-            if dot_dense_left_right[i, 1] > power_limit_valve and p_bin_sum[i] > 20:  # 如果向右扩展网格数大于阈值,且该水平功率带点总数>20,是
+        for i in range(power_bin_count - 6):
+            # 如果向右扩展网格数大于阈值,且该水平功率带点总数>20,是限功率
+            if dot_dense_left_right[i, 1] > power_limit_valve and power_bin_sum[i] > 20:
                 power_limit[i] = 1
-                n_counter_limit = n_counter_limit + 1
 
             if dot_dense_left_right[i, 1] <= power_limit_valve:
-                width_average = width_average + dot_dense_left_right[i, 1]  # 统计正常水平功率带右侧宽度
+                # 统计正常水平功率带右侧宽度
+                width_average = width_average + dot_dense_left_right[i, 1]
                 n_counter = n_counter + 1
 
         width_average = width_average / n_counter  # 功率主带平均宽度
 
-        # 各水平功率带的功率主带宽度的方差,反映从下到上宽度是否一致,或是否下宽上窄等异常情况
-        for i in range(power_num - 6):
-            if dot_dense_left_right[i, 1] <= power_limit_valve:
-                width_var = width_var + (dot_dense_left_right[i, 1] - width_average) * (
-                        dot_dense_left_right[i, 1] - width_average)
-
         # 对限负荷水平功率带的最大网格较下面相邻层显著偏右,拉回
-        for i in range(1, power_num - 6):
+        for i in range(1, power_bin_count - 6):
             if power_limit[i] == 1 and abs(p_box_max_index[i] - p_box_max_index[i - 1]) > 5:
                 p_box_max_index[i] = p_box_max_index[i - 1] + 1
 
-        # 输出各层功率主带的左右边界网格索引
-        dot_dense_inverse = np.zeros([power_num, 2], dtype=int)
-
-        for i in range(power_num):
-            dot_dense_inverse[i, :] = dot_dense_left_right[power_num - i - 1, :]
-
         # 功率主带的右边界
-        curve_width_r = int(np.ceil(width_average) + 2)
-
-        # curve_width_l = 6    #功率主带的左边界
-        curve_width_l = curve_width_r
+        curve_width = int(np.ceil(width_average) + 2)
 
-        b_box_limit = np.zeros([power_num, velocity_num], dtype=int)  # 网格是否为限功率网格的标识,如果为限功率水平功率带,从功率主带右侧边缘向右的网格为限功率网格
-        for i in range(2, power_num - 6):
-            if power_limit[i] == 1:
-                for j in range(p_box_max_index[i] + curve_width_r, velocity_num):
-                    b_box_limit[i, j] = 1
+        # 数据异常需要剔除的网格标识,标识1:功率主带右侧的欠发网格;2:功率主带左侧的超发网格 3:额定功率以上的超发点
+        b_box_remove = np.zeros([power_bin_count, velocity_bin_count], dtype=int)
 
-        b_box_remove = np.zeros([power_num, velocity_num], dtype=int)  # 数据异常需要剔除的网格标识,标识==1:功率主带右侧的欠发网格;==2:功率主带左侧的超发网格
-        for m in range(power_num - 6):
-            for n in range(p_box_max_index[m] + curve_width_r, velocity_num):
+        for m in range(power_bin_count - 6):
+            for n in range(p_box_max_index[m] + curve_width, velocity_bin_count):
                 b_box_remove[m, n] = 1
 
-            for n in range(p_box_max_index[m] - curve_width_l, -1, -1):
+            for n in range(p_box_max_index[m] - curve_width, -1, -1):
                 b_box_remove[m, n] = 2
 
         # 确定功率主带的左上拐点,即额定风速位置的网格索引
         curve_top = np.zeros(2, dtype=int)
         curve_top_valve = 3  # 网格的百分比阈值
-        b_top_find = 0
-        for m in range(power_num - 4 - 1, -1, -1):
-            for n in range(velocity_num):
-                if v_box_percent[m, n] > curve_top_valve and x_box_number[m, n] >= 10:  # 如左上角网格的百分比和散点个数大于阈值。
+        b_top_find = False
+        for m in range(power_bin_count - 5, -1, -1):
+            for n in range(velocity_bin_count):
+                # 如左上角网格的百分比和散点个数大于阈值。
+                if v_box_percent[m, n] > curve_top_valve and x_box_number[m, n] >= 10:
                     curve_top[0] = m
                     curve_top[1] = n
-                    b_top_find = 1
+                    b_top_find = True
                     break
 
-            if b_top_find == 1:
+            if b_top_find:
                 break
 
         isolate_valve = 3
-        for m in range(power_num - 6):
-            for n in range(p_box_max_index[m] + curve_width_r, velocity_num):
-                if p_box_percent[m, n] < isolate_valve:
+        for m in range(power_bin_count - 6):
+            for n in range(p_box_max_index[m] + curve_width, velocity_bin_count):
+                if power_box_percent[m, n] < isolate_valve:
                     b_box_remove[m, n] = 1
 
         # 功率主带顶部宽度
         curve_width_t = 2
-        for m in range(power_num - curve_width_t - 1, power_num):
-            for n in range(velocity_num):
+        for m in range(power_bin_count - curve_width_t - 1, power_bin_count):
+            for n in range(velocity_bin_count):
                 b_box_remove[m, n] = 3  # 网格为额定功率以上的超发点
 
         # 功率主带拐点左侧的欠发网格标识
-        for m in range(power_num - 5 - 1, power_num):
+        for m in range(power_bin_count - 5 - 1, power_bin_count):
             for n in range(curve_top[1] - 1):
                 b_box_remove[m, n] = 2
 
         # 以网格的标识,决定该网格内数据的标识。dzwind_and_power_sel。散点在哪个网格,此网格的标识即为该点的标识
-        dzwind_and_power_sel = np.zeros(n_counter1, dtype=int)  # -1:停机 0:好点  1:欠发功率点;2:超发功率点;3:额定风速以上的超发功率点 4: 限电
+        # -1:停机 0:好点  1:欠发功率点;2:超发功率点;3:额定风速以上的超发功率点 4: 限电
+        dzwind_and_power_sel = np.zeros(power_gt_zero_array_count, dtype=int)
         n_which_p = -1
         n_which_v = -1
-        n_bad_a = 0
 
-        for i in range(n_counter1):
-            for m in range(power_num):
-                if m * 25 < dz_march[i, 1] <= (m + 1) * 25:
+        for i in range(power_gt_zero_array_count):
+            for m in range(power_bin_count):
+                if m * 25 < power_gt_zero_array[i, 1] <= (m + 1) * 25:
                     n_which_p = m
                     break
 
-            for n in range(velocity_num):
-                if ((n + 1) * 0.25 - 0.125) < dz_march[i, 0] <= ((n + 1) * 0.25 + 0.125):
+            for n in range(velocity_bin_count):
+                if (n * 0.25 + 0.125) < power_gt_zero_array[i, 0] <= ((n + 1) * 0.25 + 0.125):
                     n_which_v = n
                     break
 
             if n_which_p > -1 and n_which_v > -1:
-
                 if b_box_remove[n_which_p, n_which_v] == 1:
                     dzwind_and_power_sel[i] = 1
-                    n_bad_a = n_bad_a + 1
 
                 if b_box_remove[n_which_p, n_which_v] == 2:
                     dzwind_and_power_sel[i] = 2
@@ -300,12 +271,12 @@ class ClassIdentifier(object):
         n_window_length = 3
         limit_window = np.zeros(n_window_length, dtype=float)
         power_std = 15  # 功率波动方差
-        n_window_num = int(np.floor(n_counter1 / n_window_length))
+        n_window_num = int(np.floor(power_gt_zero_array_count / n_window_length))
         power_limit_up = self.rated_power - 300
         power_limit_low = 200
         for i in range(n_window_num):
             for j in range(n_window_length):
-                limit_window[j] = dz_march[i * n_window_length + j, 1]
+                limit_window[j] = power_gt_zero_array[i * n_window_length + j, 1]
 
             b_all_in_areas = 1
             for j in range(n_window_length):
@@ -326,21 +297,22 @@ class ClassIdentifier(object):
                 for j in range(n_window_length):
                     dzwind_and_power_sel[i * n_window_length + j] = 4  # 标识窗口内的数据为限负荷数据
 
-        for i in range(power_num - 6):
+        for i in range(power_bin_count - 6):
             pv_left_down = np.zeros(2, dtype=float)
             pv_right_up = np.zeros(2, dtype=float)
 
             if (p_box_max_index[i + 1] - p_box_max_index[i]) >= 1:
-                pv_left_down[0] = (p_box_max_index[i] + 1 + curve_width_r) * 0.25 - 0.125
+                pv_left_down[0] = (p_box_max_index[i] + curve_width) * 0.25 + 0.125
                 pv_left_down[1] = i * 25
 
-                pv_right_up[0] = (p_box_max_index[i + 1] + 1 + curve_width_r) * 0.25 - 0.125
+                pv_right_up[0] = (p_box_max_index[i + 1] + curve_width) * 0.25 + 0.125
                 pv_right_up[1] = (i + 1) * 25
 
-                for m in range(n_counter1):
-                    if pv_left_down[0] < dz_march[m, 0] < pv_right_up[0] and pv_left_down[1] < \
-                            dz_march[m, 1] < pv_right_up[1]:  # 在该锯齿中
-                        if (dz_march[m, 1] - pv_left_down[1]) / (dz_march[m, 0] - pv_left_down[0]) > (
+                for m in range(power_gt_zero_array_count):
+                    if pv_left_down[0] < power_gt_zero_array[m, 0] < pv_right_up[0] and \
+                            pv_left_down[1] < power_gt_zero_array[m, 1] < pv_right_up[1]:  # 在该锯齿中
+                        if (power_gt_zero_array[m, 1] - pv_left_down[1]) / (
+                                power_gt_zero_array[m, 0] - pv_left_down[0]) > (
                                 pv_right_up[1] - pv_left_down[1]) / (
                                 pv_right_up[0] - pv_left_down[0]):  # 斜率大于对角连线,则在锯齿左上三角形中,选中
                             dzwind_and_power_sel[m] = 0

+ 4 - 3
etl/step/StatisticsAndSaveFile.py

@@ -82,8 +82,9 @@ class StatisticsAndSaveFile(object):
 
         # 转化风机名称
         trans_print("开始转化风机名称")
+        origin_wind_name = str(df['wind_turbine_number'].values[0])
         df['wind_turbine_number'] = df['wind_turbine_number'].astype('str')
-        df['wind_turbine_name'] = df['wind_turbine_number']
+        # df['wind_turbine_name'] = df['wind_turbine_number']
         df['wind_turbine_number'] = df['wind_turbine_number'].map(
             self.trans_param.wind_col_trans).fillna(df['wind_turbine_number'])
         wind_col_name = str(df['wind_turbine_number'].values[0])
@@ -128,7 +129,6 @@ class StatisticsAndSaveFile(object):
         df = df[[i for i in self.trans_param.cols_tran.keys() if i in df.columns]]
         print_memory_usage("删减无用字段后内存占用:" + wind_col_name)
 
-
         rated_power_and_cutout_speed_tuple = read_conf(self.rated_power_and_cutout_speed_map, str(wind_col_name))
         if rated_power_and_cutout_speed_tuple is None:
             rated_power_and_cutout_speed_tuple = (None, None)
@@ -147,6 +147,8 @@ class StatisticsAndSaveFile(object):
             lambda x: x.strftime('%Y-%m-%d %H:%M:%S'))
         print_memory_usage("添加年月日后:" + wind_col_name)
 
+        df['wind_turbine_name'] = str(origin_wind_name)
+
         if self.paths_and_table.save_zip:
             save_path = os.path.join(self.paths_and_table.get_save_path(), str(wind_col_name) + '.csv.gz')
         else:
@@ -179,7 +181,6 @@ class StatisticsAndSaveFile(object):
                                                round(50 + 20 * (index + 1) / len(all_arrays), 2),
                                                self.paths_and_table.save_db)
 
-
         except Exception as e:
             trans_print(traceback.format_exc())
             message = "保存文件错误,系统返回错误:" + str(e)

+ 0 - 756
tmp_file/ClassIdentifier_1.py

@@ -1,756 +0,0 @@
-import numpy as np
-from pandas import DataFrame
-
-from service.plt_service import get_base_wind_and_power
-from utils.file.trans_methods import read_file_to_df
-
-
-class ClassIdentifier(object):
-
-    def __init__(self, wind_turbine_number, file_path: str = None, origin_df: DataFrame = None, index='time_stamp',
-                 wind_velocity='wind_velocity',
-                 active_power='active_power'):
-        """
-        :param wind_turbine_number: The wind turbine number.
-        :param file_path: The file path of the input data.
-        :param origin_df: The pandas DataFrame containing the input data.
-        :param index: 索引字段
-        :param wind_velocity: 风速字段
-        :param active_power: 有功功率字段
-        """
-        self.wind_turbine_number = wind_turbine_number
-        self.index = index
-        self.wind_velocity = wind_velocity
-        self.active_power = active_power
-
-        self.rated_wind_speed = 'rated_wind_speed'
-        self.rated_capacity = 'rated_capacity'
-
-        if file_path is None and origin_df is None:
-            raise ValueError("Either file_path or origin_df should be provided.")
-
-        if file_path:
-            self.df = read_file_to_df(file_path)
-        else:
-            self.df = origin_df
-
-        self.df = self.df.set_index(keys=self.index)
-
-    def identifier(self):
-        # 风速 和 有功功率 df
-        wind_and_power_df = self.df[[self.wind_velocity, self.active_power]]
-        wind_and_power_df.reset_index(inplace=True)
-        wind_and_power_df_count = wind_and_power_df.shape[0]
-        PowerMax = wind_and_power_df[self.active_power].max()
-        PowerRated = np.ceil(PowerMax / 100) * 100
-        PRated = 1500  # 额定功率1500kw,可改为2000kw
-        VCutOut = 25
-        VCutIn = 3
-        VRated = 10
-        # 网格法确定风速风向分区数量,功率方向分区数量,
-        # PNum = (PRated+100)/25  #功率分区间隔25kW
-        PNum = int(np.ceil(PowerRated / 25))  # 功率分区间隔25kW
-        VNum = int(np.ceil(VCutOut / 0.25))  # 风速分区间隔0.25m/s
-
-        # 实发电量
-        EPActualTotal = 0  # 实发电量
-        for i in range(wind_and_power_df_count):
-            if wind_and_power_df.loc[i, self.active_power] >= 0:
-                EPActualTotal = EPActualTotal + wind_and_power_df.loc[i, self.active_power] / 6
-
-        print("EPActualTotal", EPActualTotal)
-        # 平均风速
-        WindSpeedAvr = 0
-        WindSum = 0
-        for i in range(wind_and_power_df_count):
-            if wind_and_power_df.loc[i, self.wind_velocity] >= 0:
-                WindSum = WindSum + wind_and_power_df.loc[i, self.wind_velocity]
-        WindSpeedAvr = WindSum / wind_and_power_df_count
-        print("windSpeedAvr", WindSpeedAvr)
-        # 用于计算损失电量的标杆功率曲线,可更换为风机设计功率曲线
-        # base_wind_and_power_df = get_base_wind_and_power(self.wind_turbine_number)
-        base_wind_and_power_df = read_file_to_df(r"D:\中能智能\matlib计算相关\好点坏点matlib计算\A型风机设计功率曲线.csv", header=None)
-        base_wind_and_power_df.columns = [self.rated_wind_speed, self.rated_capacity]
-        if base_wind_and_power_df.empty:
-            raise ValueError("风场编号:" + self.wind_turbine_number + "未查询到风速功率信息")
-        base_wind_and_power_count = base_wind_and_power_df.shape[0]
-
-        # 风机可利用率,计算方法:大于切入风速但发电功率小于0
-        TurbineRunRate = 0
-        nShouldGP = 0
-        nRealGP = 0
-        for i in range(wind_and_power_df_count):
-            if wind_and_power_df.loc[i, self.wind_velocity] >= VCutIn:
-                nShouldGP = nShouldGP + 1
-                if wind_and_power_df.loc[i, self.active_power] > 0:
-                    nRealGP = nRealGP + 1
-        if nShouldGP > 0:
-            TurbineRunRate = nRealGP / nShouldGP * 100
-
-        print("disp(TurbineRunRate)", TurbineRunRate)
-        # 理论电量-
-        EPIdealTotalAAA = 0  # 理论电量-
-        nWhichBin = 0
-        IdealPower = 0
-        for i in range(wind_and_power_df_count):
-            # 应发电量-理论
-            nWhichBin = 0
-            for m in range(base_wind_and_power_count - 1):
-                if base_wind_and_power_df.loc[m, self.rated_wind_speed] < wind_and_power_df.loc[
-                    i, self.wind_velocity] <= \
-                        base_wind_and_power_df.loc[m + 1, self.rated_wind_speed]:
-                    nWhichBin = m
-                    break
-
-            # 插值计算对应设计功率
-            if nWhichBin > base_wind_and_power_count - 1 or nWhichBin == 0:
-                continue
-
-            IdealPower = (wind_and_power_df.loc[i, self.wind_velocity] - base_wind_and_power_df.loc[nWhichBin,
-                                                                                                    self.rated_wind_speed]) / (
-                                 base_wind_and_power_df.loc[nWhichBin + 1, self.rated_wind_speed] -
-                                 base_wind_and_power_df.loc[nWhichBin, self.rated_wind_speed]) * (
-                                 base_wind_and_power_df.loc[nWhichBin + 1, self.rated_capacity] -
-                                 base_wind_and_power_df.loc[nWhichBin, self.rated_capacity]) \
-                         + base_wind_and_power_df.loc[nWhichBin, self.rated_capacity]
-            EPIdealTotalAAA = EPIdealTotalAAA + IdealPower / 6
-
-        print('EPIdealTotalAAA', EPIdealTotalAAA)
-        #
-        # 存储功率大于零的运行数据
-        DzMarch809 = np.zeros([wind_and_power_df_count, 2], dtype=float)
-        nCounter1 = 0
-        for i in range(wind_and_power_df_count):
-            if wind_and_power_df.loc[i, self.active_power] > 0:
-                DzMarch809[nCounter1, 0] = wind_and_power_df.loc[i, self.wind_velocity]
-                DzMarch809[nCounter1, 1] = wind_and_power_df.loc[i, self.active_power]
-
-                nCounter1 = nCounter1 + 1
-
-        print('nCounter1', nCounter1)
-
-        # 统计各网格落入的散点个数
-        XBoxNumber = np.ones([PNum, VNum], dtype=int)
-        nWhichP = -1
-        nWhichV = -1
-        for i in range(nCounter1):
-            for m in range(PNum):
-                if m * 25 < DzMarch809[i, 1] <= (m + 1) * 25:
-                    nWhichP = m
-                    break
-            for n in range(VNum):
-                if ((n + 1) * 0.25 - 0.125) < DzMarch809[i, 0] <= ((n + 1) * 0.25 + 0.125):
-                    nWhichV = n
-                    break
-
-            if nWhichP > -1 and nWhichV > -1:
-                XBoxNumber[nWhichP, nWhichV] = XBoxNumber[nWhichP, nWhichV] + 1
-
-        for m in range(PNum):
-            for n in range(VNum):
-                XBoxNumber[m, n] = XBoxNumber[m, n] - 1
-
-        print('XBoxNumber', XBoxNumber)
-        # 在功率方向将网格内散点绝对个数转换为相对百分比,备用
-        PBoxPercent = np.zeros([PNum, VNum], dtype=float)
-        PBinSum = np.zeros(PNum, dtype=int)
-
-        for i in range(PNum):
-            for m in range(VNum):
-                PBinSum[i] = PBinSum[i] + XBoxNumber[i, m]
-
-            for m in range(VNum):
-                if PBinSum[i] > 0:
-                    PBoxPercent[i, m] = XBoxNumber[i, m] / PBinSum[i] * 100
-
-        # 在风速方向将网格内散点绝对个数转换为相对百分比,备用
-        VBoxPercent = np.zeros([PNum, VNum], dtype=float)
-        VBinSum = np.zeros(VNum, dtype=int)
-
-        for i in range(VNum):
-            for m in range(PNum):
-                VBinSum[i] = VBinSum[i] + XBoxNumber[m, i]
-
-            for m in range(PNum):
-                if VBinSum[i] > 0:
-                    VBoxPercent[m, i] = XBoxNumber[m, i] / VBinSum[i] * 100
-
-        # 以水平功率带方向为准,分析每个水平功率带中,功率主带中心,即找百分比最大的网格位置。
-        PBoxMaxIndex = np.zeros(PNum, dtype=int)  # 水平功率带最大网格位置索引
-        PBoxMaxP = np.zeros(PNum, dtype=int)  # 水平功率带最大网格百分比
-
-        for m in range(PNum):
-            # 确定每一水平功率带的最大网格位置索引即百分比值
-            PBoxMaxP[m], PBoxMaxIndex[m] = PBoxPercent[m, :].max(), PBoxPercent[m, :].argmax()
-
-        # 以垂直风速方向为准,分析每个垂直风速带中,功率主带中心,即找百分比最大的网格位置。
-        VBoxMaxIndex = np.zeros(VNum, dtype=int)
-        VBoxMaxV = np.zeros(VNum, dtype=int)
-
-        for m in range(VNum):
-            [VBoxMaxV[m], VBoxMaxIndex[m]] = VBoxPercent[:, m].max(), VBoxPercent[:, m].argmax()
-
-        # 切入风速特殊处理,如果切入风速过于偏右,向左拉回
-        if PBoxMaxIndex[0] > 14:
-            PBoxMaxIndex[0] = 9
-
-        # 以水平功率带方向为基准,进行分析
-        DotDense = np.zeros(PNum, dtype=int)  # 每一水平功率带的功率主带包含的网格数
-        DotDenseLeftRight = np.zeros([PNum, 2], dtype=int)  # 存储每一水平功率带的功率主带以最大网格为中心,向向左,向右扩展的网格数
-        DotValve = 90  # 从中心向左右对称扩展网格的散点百分比和的阈值。
-        PDotDenseSum = 0
-
-        iSpreadLeft = 1  # 向左扩展网格计数,初值为1
-        iSpreadRight = 1  # 向右扩展网格技术,初值为1
-        for i in range(PNum - 6):  # 从最下层水平功率带1开始,向上到第PNum-6个水平功率带(额定功率一下水平功率带),逐一分析
-            PDotDenseSum = PBoxMaxP[i]  # 以中心最大水平功率带为基准,向左向右对称扩展网格,累加各网格散点百分比
-            iSpreadRight = 1
-            iSpreadLeft = 1
-            while PDotDenseSum < DotValve:
-
-                if (PBoxMaxIndex[i] + iSpreadRight) < VNum - 1:
-                    PDotDenseSum = PDotDenseSum + PBoxPercent[i, PBoxMaxIndex[i] + iSpreadRight]  # 向右侧扩展
-                    iSpreadRight = iSpreadRight + 1
-
-                if (PBoxMaxIndex[i] + iSpreadRight) > VNum - 1:
-                    break
-
-                if (PBoxMaxIndex[i] - iSpreadLeft) > 0:
-                    PDotDenseSum = PDotDenseSum + PBoxPercent[i, PBoxMaxIndex[i] - iSpreadLeft]  # 向左侧扩展
-                    iSpreadLeft = iSpreadLeft + 1
-
-                if (PBoxMaxIndex[i] - iSpreadLeft) <= 0:
-                    break
-
-            iSpreadRight = iSpreadRight - 1
-
-            iSpreadLeft = iSpreadLeft - 1
-            # 向左右对称扩展完毕
-
-            DotDenseLeftRight[i, 0] = iSpreadLeft
-            DotDenseLeftRight[i, 1] = iSpreadRight
-            DotDense[i] = iSpreadLeft + iSpreadRight + 1
-
-        # 各行功率主带右侧宽度的中位数最具有代表性
-        DotDenseWidthLeft = np.zeros([PNum - 6, 1], dtype=int)
-        for i in range(PNum - 6):
-            DotDenseWidthLeft[i] = DotDenseLeftRight[i, 1]
-
-        MainBandRight = np.median(DotDenseWidthLeft)
-
-        # 散点向右显著延展分布的水平功率带为限功率水平带
-        PowerLimit = np.zeros([PNum, 1], dtype=int)  # 各水平功率带是否为限功率标识,==1:是;==0:不是
-        WidthAverage = 0  # 功率主带平均宽度
-        WidthVar = 0  # 功率主带方差
-        # PowerLimitValve = 6    #限功率主带判别阈值
-        PowerLimitValve = np.ceil(MainBandRight) + 3  # 限功率主带判别阈值
-
-        nCounterLimit = 0
-        nCounter = 0
-
-        for i in range(PNum - 6):
-            if DotDenseLeftRight[i, 1] > PowerLimitValve and PBinSum[i] > 20:  # 如果向右扩展网格数大于阈值,且该水平功率带点总数>20,是
-                PowerLimit[i] = 1
-                nCounterLimit = nCounterLimit + 1
-
-            if DotDenseLeftRight[i, 1] <= PowerLimitValve:
-                WidthAverage = WidthAverage + DotDenseLeftRight[i, 1]  # 统计正常水平功率带右侧宽度
-                nCounter = nCounter + 1
-
-        WidthAverage = WidthAverage / nCounter  # 功率主带平均宽度
-
-        print("WidthAverage", WidthAverage)
-
-        # 各水平功率带的功率主带宽度的方差,反映从下到上宽度是否一致,或是否下宽上窄等异常情况
-        for i in range(PNum - 6):
-            if DotDenseLeftRight[i, 1] <= PowerLimitValve:
-                WidthVar = WidthVar + (DotDenseLeftRight[i, 1] - WidthAverage) * (
-                        DotDenseLeftRight[i, 1] - WidthAverage)
-
-        WidthVar = np.sqrt(WidthVar / nCounter)
-
-        # 各水平功率带,功率主带的风速范围,右侧扩展网格数*2*0.25
-        PowerBandWidth = WidthAverage * 2 * 0.25
-
-        # 对限负荷水平功率带的最大网格较下面相邻层显著偏右,拉回
-        for i in range(1, PNum - 6):
-            if PowerLimit[i] == 1 and abs(PBoxMaxIndex[i] - PBoxMaxIndex[i - 1]) > 5:
-                PBoxMaxIndex[i] = PBoxMaxIndex[i - 1] + 1
-
-        # 输出各层功率主带的左右边界网格索引
-        DotDenseInverse = np.zeros([PNum, 2], dtype=int)
-
-        for i in range(PNum):
-            DotDenseInverse[i, :] = DotDenseLeftRight[PNum - i - 1, :]
-
-        # print('DotDenseInverse', DotDenseInverse)
-
-        # 功率主带的右边界
-        CurveWidthR = int(np.ceil(WidthAverage) + 2)
-
-        # CurveWidthL = 6    #功率主带的左边界
-        CurveWidthL = CurveWidthR
-
-        BBoxLimit = np.zeros([PNum, VNum], dtype=int)  # 网格是否为限功率网格的标识,如果为限功率水平功率带,从功率主带右侧边缘向右的网格为限功率网格
-        for i in range(2, PNum - 6):
-            if PowerLimit[i] == 1:
-                for j in range(PBoxMaxIndex[i] + CurveWidthR, VNum):
-                    BBoxLimit[i, j] = 1
-
-        BBoxRemove = np.zeros([PNum, VNum], dtype=int)  # 数据异常需要剔除的网格标识,标识==1:功率主带右侧的欠发网格;==2:功率主带左侧的超发网格
-        for m in range(PNum - 6):
-            for n in range(PBoxMaxIndex[m] + CurveWidthR - 1, VNum):
-                BBoxRemove[m, n] = 1
-
-            for n in range(PBoxMaxIndex[m] - CurveWidthL - 1, 0, -1):
-                BBoxRemove[m, n] = 2
-
-        # 确定功率主带的左上拐点,即额定风速位置的网格索引
-        CurveTop = np.zeros(2, dtype=int)
-        CurveTopValve = 3  # 网格的百分比阈值
-        BTopFind = 0
-        for m in range(PNum - 4 - 1, 0, -1):
-            for n in range(VNum):
-                if VBoxPercent[m, n] > CurveTopValve and XBoxNumber[m, n] >= 10:  # 如左上角网格的百分比和散点个数大于阈值。
-                    CurveTop[0] = m
-                    CurveTop[1] = n
-                    BTopFind = 1
-                    break
-
-            if BTopFind == 1:
-                break
-
-        IsolateValve = 3
-        for m in range(PNum - 6):
-            for n in range(PBoxMaxIndex[m] + CurveWidthR - 1, VNum):
-                if PBoxPercent[m, n] < IsolateValve:
-                    BBoxRemove[m, n] = 1
-
-        # 功率主带顶部宽度
-        CurveWidthT = 2
-        for m in range(PNum - CurveWidthT - 1, PNum):
-            for n in range(VNum):
-                BBoxRemove[m, n] = 3  # 网格为额定功率以上的超发点
-
-        # 功率主带拐点左侧的欠发网格标识
-        for m in range(PNum - 5 - 1, PNum):
-            for n in range(CurveTop[1] - 2 - 1):
-                BBoxRemove[m, n] = 2
-
-        # 以网格的标识,决定该网格内数据的标识。Dzwind_and_power_dfSel功率非零数据的标识位。散点在哪个网格,此网格的标识即为该点的标识
-        Dzwind_and_power_dfSel = np.zeros(nCounter1, dtype=int)  # is ==1,欠发功率点;==2,超发功率点;==3,额定风速以上的超发功率点 ==4, 限电
-        nWhichP = 0
-        nWhichV = 0
-        nBadA = 0
-
-        for i in range(nCounter1):
-            for m in range(PNum):
-                if DzMarch809[i, 1] > (m - 1) * 25 and DzMarch809[i, 1] <= m * 25:
-                    nWhichP = m
-                    break
-
-            for n in range(VNum):
-                if DzMarch809[i, 0] > (n * 0.25 - 0.125) and DzMarch809[i, 0] <= (n * 0.25 + 0.125):
-                    nWhichV = n
-                    break
-
-            if nWhichP > 0 and nWhichV > 0:
-
-                if BBoxRemove[nWhichP, nWhichV] == 1:
-                    Dzwind_and_power_dfSel[i] = 1
-                    nBadA = nBadA + 1
-
-                if BBoxRemove[nWhichP, nWhichV] == 2:
-                    Dzwind_and_power_dfSel[i] = 2
-
-                if BBoxRemove[nWhichP, nWhichV] == 3:
-                    Dzwind_and_power_dfSel[i] = 0  # 3  # 额定风速以上的超发功率点认为是正常点,不再标识。
-
-                if BBoxLimit[nWhichP, nWhichV] == 1 and nWhichP>16:
-                    Dzwind_and_power_dfSel[i] = 4
-
-        print("nWhichP", nWhichP)
-        print("nWhichV", nWhichV)
-        print("nBadA", nBadA)
-
-        # 限负荷数据标识方法2:把数据切割为若干个窗口。对每一窗口,以第一个点为基准,连续nWindowLength个数据的功率在方差范围内,呈现显著水平分布的点
-        PVLimit = np.zeros([nCounter1, 2], dtype=int)  # 存储限负荷数据
-        nLimitTotal = 0
-        nWindowLength = 3
-        LimitWindow = np.zeros(nWindowLength, dtype=int)
-        UpLimit = 0  # 上限
-        LowLimit = 0  # 下限
-        PowerStd = 15  # 功率波动方差
-        bAllInUpLow = 1  # ==1:窗口内所有数据均在方差上下限之内,限负荷==0,不满足条件
-        bAllInAreas = 1  # ==1:窗口所有数据均在200~PRated-300kW范围内;==0:不满足此条件
-        nWindowNum = int(np.floor(nCounter1 / nWindowLength))
-        PowerLimitUp = PRated - 300
-        PowerLimitLow = 200
-        for i in range(nWindowNum):
-            for j in range(nWindowLength):
-                LimitWindow[j] = DzMarch809[i * nWindowLength + j, 1]
-
-            bAllInAreas = 1
-            for j in range(nWindowLength):
-                if LimitWindow[j] < PowerLimitLow or LimitWindow[j] > PowerLimitUp:
-                    bAllInAreas = 0
-
-            if bAllInAreas == 0:
-                continue
-
-            UpLimit = LimitWindow[0] + PowerStd
-            LowLimit = LimitWindow[0] - PowerStd
-            bAllInUpLow = 1
-            for j in range(1, nWindowLength):
-                if LimitWindow[j] < LowLimit or LimitWindow[j] > UpLimit:
-                    bAllInUpLow = 0
-
-            if bAllInUpLow == 1:
-                for j in range(nWindowLength):
-                    Dzwind_and_power_dfSel[i * nWindowLength + j] = 4  # 标识窗口内的数据为限负荷数据
-
-                for j in range(nWindowLength):
-                    PVLimit[nLimitTotal, :] = DzMarch809[i * nWindowLength + j, :]
-                    nLimitTotal = nLimitTotal + 1
-
-        print("nLimitTotal", nLimitTotal)
-
-        # 相邻水平功率主带的锯齿平滑
-        PVLeftDown = np.zeros(2, dtype=int)
-        PVRightUp = np.zeros(2, dtype=int)
-        nSmooth = 0
-        for i in range(PNum - 6 - 1):
-            PVLeftDown = np.zeros(2, dtype=int)
-            PVRightUp = np.zeros(2, dtype=int)
-
-            if (PBoxMaxIndex[i + 1] - PBoxMaxIndex[i]) >= 1:
-                PVLeftDown[0] = (PBoxMaxIndex[i] + CurveWidthR) * 0.25 - 0.125
-                PVLeftDown[1] = (i - 1) * 25
-
-                PVRightUp[0] = (PBoxMaxIndex[i + 1] + CurveWidthR) * 0.25 - 0.125
-                PVRightUp[1] = (i + 1 - 1) * 25
-
-                for m in range(nCounter1):
-                    if DzMarch809[m, 0] > PVLeftDown[0] and DzMarch809[m, 0] < PVRightUp[0] and PVLeftDown[1] < \
-                            DzMarch809[m, 1] < PVRightUp[1]:  # 在该锯齿中
-                        if (DzMarch809[m, 1] - PVLeftDown[1]) / (DzMarch809[m, 0] - PVLeftDown[0]) > (
-                                PVRightUp[1] - PVLeftDown[1]) / (
-                                PVRightUp[0] - PVLeftDown[0]):  # 斜率大于对角连线,则在锯齿左上三角形中,选中
-                            Dzwind_and_power_dfSel[m] = 0
-                            nSmooth = nSmooth + 1
-
-        print("nSmooth", nSmooth)
-
-        # 存储好点
-        nCounterPV = 0
-        PVDot = np.zeros([nCounter1, 2], dtype=int)
-        for i in range(nCounter1):
-            if Dzwind_and_power_dfSel[i] == 0:
-                PVDot[nCounterPV, :] = DzMarch809[i, :]
-                nCounterPV = nCounterPV + 1
-
-        nCounterVP = nCounterPV
-        print("nCounterVP", nCounterVP)
-
-        # 存储坏点
-        nCounterBad = 0
-        PVBad = np.zeros([nCounter1, 2], dtype=int)
-        for i in range(nCounter1):
-            if Dzwind_and_power_dfSel[i] == 1 or Dzwind_and_power_dfSel[i] == 2 or Dzwind_and_power_dfSel[i] == 3:
-                PVBad[nCounterBad, :] = DzMarch809[i, :]
-                nCounterBad = nCounterBad + 1
-
-        print("nCounterBad", nCounterBad)
-
-        # 用功率主带中的好点绘制实测功率曲
-        XBinNumber = np.ones(50, dtype=int)
-        PCurve = np.zeros([50, 2], dtype=int)
-        PCurve[:, 0] = [i / 2 for i in range(1, 51)]
-        XBinSum = np.zeros([50, 2], dtype=int)
-        nWhichBin = 0
-
-        for i in range(nCounterVP):
-            nWhichBin = 0
-
-            for b in range(50):
-                if PVDot[i, 0] > (b * 0.5 - 0.25) and PVDot[i, 0] <= (b * 0.5 + 0.25):
-                    nWhichBin = b
-                    break
-
-            if nWhichBin > 0:
-                XBinSum[nWhichBin, 0] = XBinSum[nWhichBin, 0] + PVDot[i, 0]  # wind speed
-                XBinSum[nWhichBin, 1] = XBinSum[nWhichBin, 1] + PVDot[i, 1]  # Power
-                XBinNumber[nWhichBin] = XBinNumber[nWhichBin] + 1
-
-        for b in range(50):
-            XBinNumber[b] = XBinNumber[b] - 1
-
-        for b in range(50):
-            if XBinNumber[b] > 0:
-                PCurve[b, 0] = XBinSum[b, 0] / XBinNumber[b]
-                PCurve[b, 1] = XBinSum[b, 1] / XBinNumber[b]
-
-        # 对额定风速以上的功率直接赋额定功率
-        VRatedNum = int(VRated / 0.5)
-        for m in range(VRatedNum, 50):
-            if PCurve[m, 1] == 0:
-                PCurve[m, 1] = PRated
-
-        # print("PCurve", PCurve)
-
-        # 绘制标准正则功率曲线,以0.5m/s标准为间隔
-        # 15m/s以上为额定功率,15m/s以下为计算得到
-        PCurveNorm = np.zeros([50, 2], dtype=int)
-        for i in range(30, 50):
-            PCurveNorm[i, 0] = i * 0.5
-            PCurveNorm[i, 1] = PRated
-
-        # 15m/s一下正则功率曲线
-        CurveData = np.zeros([30, 2], dtype=int)
-        for i in range(30):
-            CurveData[i, :] = PCurve[i, :]
-
-        CurveNorm = np.zeros([30, 2], dtype=int)
-        VSpeed = [i / 2 for i in range(1, 31)]
-
-        WhichBin = 0
-
-        K = 0
-        a = 0
-        for m in range(30):
-            K = 0
-            a = 0
-
-            for n in range(30):
-                if abs(CurveData[n, 0] - VSpeed[m]) < 0.1:
-                    WhichBin = n
-                    break
-
-            if WhichBin > 1:
-                if CurveData[WhichBin, 0] - CurveData[WhichBin - 1, 0] > 0:
-                    K = (CurveData[WhichBin, 1] - CurveData[WhichBin - 1, 1]) / (
-                            CurveData[WhichBin, 0] - CurveData[WhichBin - 1, 0])
-                    a = CurveData[WhichBin, 1] - K * CurveData[WhichBin, 0]
-
-            CurveNorm[m, 0] = VSpeed[m]
-            CurveNorm[m, 1] = a + K * VSpeed[m]
-
-        for i in range(30):
-            PCurveNorm[i, :] = CurveNorm[i, :]
-
-        # 子模块3:损失电量计算及发电性能评价
-        CC = len(PCurve[:, 0])
-        EPIdealTotal = 0
-        # 计算停机损失
-        EPLostStopTotal = 0
-        EPLost = 0
-
-        nWhichBin = 0
-        IdealPower = 0
-        nStopTotal = 0
-        for i in range(wind_and_power_df_count):
-            if wind_and_power_df.loc[i, self.active_power] <= 0:
-                nWhichBin = 0
-                for m in range(base_wind_and_power_count - 1):
-                    if wind_and_power_df.loc[i, self.wind_velocity] > base_wind_and_power_df.loc[
-                        m, self.rated_wind_speed] and wind_and_power_df.loc[i, self.wind_velocity] <= \
-                            base_wind_and_power_df.loc[
-                                m + 1, self.rated_wind_speed]:
-                        nWhichBin = m
-                        break
-
-                if nWhichBin > base_wind_and_power_count - 1 or nWhichBin == 0:
-                    continue
-
-                IdealPower = (wind_and_power_df.loc[i, self.wind_velocity] - base_wind_and_power_df.loc[
-                    nWhichBin, self.rated_wind_speed]) / (
-                                     base_wind_and_power_df.loc[nWhichBin + 1, self.rated_wind_speed] -
-                                     base_wind_and_power_df.loc[
-                                         nWhichBin, self.rated_wind_speed]) * (
-                                     base_wind_and_power_df.loc[nWhichBin + 1, self.rated_capacity]
-                                     - base_wind_and_power_df.loc[nWhichBin, self.rated_capacity]) \
-                             + base_wind_and_power_df.loc[nWhichBin, self.rated_capacity]
-
-                EPLost = IdealPower / 6
-                EPLostStopTotal = EPLostStopTotal + EPLost
-                nStopTotal = nStopTotal + 1
-
-        print("EPLost", EPLost)
-        print("nStopTotal", nStopTotal)
-        print("EPLostStopTotal", EPLostStopTotal)
-
-        nWhichP = 0
-        nWhichV = 0
-        nWhichBin = 0
-        IdealPower = 0
-
-        # 计算欠发损失,此欠发损失已不包括限电损失,限电点在前面已经从欠发点中去除。
-        EPLostBadTotal = 0
-        EPLost = 0
-
-        nBadTotal = 0
-
-        LostBadPercent = 0
-
-        EPOverTotal = 0
-        EPOver = 0
-        nOverTotal = 0
-
-        for i in range(nCounter1):
-            if Dzwind_and_power_dfSel[i] == 1:
-                nWhichBin = 0
-                for m in range(base_wind_and_power_count - 1):
-                    if DzMarch809[i, 0] > base_wind_and_power_df.loc[m, self.rated_wind_speed] \
-                            and DzMarch809[i, 0] <= base_wind_and_power_df.loc[m + 1, self.rated_wind_speed]:
-                        nWhichBin = m
-                        break
-
-                if nWhichBin > base_wind_and_power_count - 1 or nWhichBin == 0:
-                    continue
-
-                IdealPower = (DzMarch809[i, 0] - base_wind_and_power_df.loc[nWhichBin, self.rated_wind_speed]) / (
-                        base_wind_and_power_df.loc[nWhichBin + 1, self.rated_wind_speed] - base_wind_and_power_df.loc[
-                    nWhichBin, self.rated_wind_speed]) * (
-                                     base_wind_and_power_df.loc[nWhichBin + 1, self.rated_capacity] -
-                                     base_wind_and_power_df.loc[nWhichBin, self.rated_capacity]) + \
-                             base_wind_and_power_df.loc[nWhichBin, self.rated_capacity]
-                EPLost = abs(IdealPower - DzMarch809[i, 1]) / 6
-                EPLostBadTotal = EPLostBadTotal + EPLost
-                nBadTotal = nBadTotal + 1
-
-            # 额定风速以上超发电量
-            if Dzwind_and_power_dfSel[i] == 3:
-                EPOver = (DzMarch809[i, 1] - PRated) / 6
-                EPOverTotal = EPOverTotal + EPOver
-                nOverTotal = nOverTotal + 1
-
-        print("EPLost", EPLost)
-        print("nBadTotal", nBadTotal)
-        print("EPLostBadTotal", EPLostBadTotal)
-        print("EPOverTotal", EPOverTotal)
-        print("nOverTotal", nOverTotal)
-
-        # 功率曲线未达标损失
-        EPLostPerformTotal = 0
-        nWhichBinI = 0
-        IdealPower = 0
-
-        for i in range(nCounterVP):
-
-            for m in range(base_wind_and_power_count - 1):
-                if PVDot[i, 0] > base_wind_and_power_df.loc[m, self.rated_wind_speed] and PVDot[i, 0] <= \
-                        base_wind_and_power_df.loc[m + 1, self.rated_wind_speed]:
-                    nWhichBinI = m
-                    break
-
-            if nWhichBinI > base_wind_and_power_count - 1 or nWhichBinI == 0:
-                continue
-
-            IdealPower = (PVDot[i, 0] - base_wind_and_power_df.loc[nWhichBinI, self.rated_wind_speed]) / (
-                    base_wind_and_power_df.loc[nWhichBinI + 1, self.rated_wind_speed] - base_wind_and_power_df.loc[
-                nWhichBinI, self.rated_wind_speed]) * \
-                         (base_wind_and_power_df.loc[nWhichBinI + 1, self.rated_capacity] -
-                          base_wind_and_power_df.loc[nWhichBinI, self.rated_capacity]) + \
-                         base_wind_and_power_df.loc[nWhichBinI, self.rated_capacity]
-
-            EPLostPerformTotal = EPLostPerformTotal + (IdealPower - PVDot[i, 1]) / 6
-
-        print("EPLostPerformTotal", EPLostPerformTotal)
-
-        # 限电损失
-        EPLostLimitTotal = 0
-        EPLost = 0
-        nLimitTotal = 0
-
-        PVLimit = np.zeros([nCounter1, 2])
-
-        for i in range(nCounter1):
-            if Dzwind_and_power_dfSel[i] == 4:
-                nWhichBin = 0
-                for m in range(base_wind_and_power_count - 1):
-                    if DzMarch809[i, 0] > base_wind_and_power_df.loc[m, self.rated_wind_speed] and DzMarch809[i, 0] <= \
-                            base_wind_and_power_df.loc[m + 1, self.rated_wind_speed]:
-                        nWhichBin = m
-                        break
-
-                # 插值计算对应设计功率
-                if nWhichBin > base_wind_and_power_count - 1 or nWhichBin == 0:
-                    continue
-
-                IdealPower = (DzMarch809[i, 0] - base_wind_and_power_df.loc[nWhichBin, self.rated_wind_speed]) / (
-                        base_wind_and_power_df.loc[nWhichBin + 1, self.rated_wind_speed] -
-                        base_wind_and_power_df.loc[nWhichBin, self.rated_wind_speed]) * (
-                                     base_wind_and_power_df.loc[nWhichBin + 1, self.rated_capacity] -
-                                     base_wind_and_power_df.loc[nWhichBin, self.rated_capacity]) + \
-                             base_wind_and_power_df.loc[nWhichBin, self.rated_capacity]
-                EPLost = np.abs(IdealPower - DzMarch809[i, 1]) / 6
-                EPLostLimitTotal = EPLostLimitTotal + EPLost
-
-                PVLimit[nLimitTotal, :] = DzMarch809[i, :]
-                nLimitTotal = nLimitTotal + 1
-
-        nLimitTotal = nLimitTotal - 1
-
-        print("nLimitTotal", nLimitTotal)
-
-        # 欠发和限点损失总和
-        EPLostBadLimitTotal = EPLostBadTotal + EPLostLimitTotal
-
-        # 如果功率曲线未达标损失为正
-        if EPLostPerformTotal >= 0:
-            EPIdealTotal = EPActualTotal + EPLostStopTotal + EPLostLimitTotal + EPLostBadTotal + EPLostPerformTotal
-
-        # 如果功率曲线未达标损失为负
-        if EPLostPerformTotal < 0:
-            EPIdealTotal = EPActualTotal + EPLostStopTotal + EPLostLimitTotal + EPLostBadTotal
-
-        print("EPIdealTotal", EPIdealTotal)
-        # 可以比较求和得到的应发功率EPIdealTotal与理论计算得到的应发功率EPIdealTotalAAA的差别
-        # 需要去除的超发功率:(1)功率主带左侧的超发点;(2)额定风速以上的超发点。
-        RemoveOverEP = 0
-        nType2 = 0
-        for i in range(nCounter1):
-            if Dzwind_and_power_dfSel[i] == 2:  # 功率主带左侧的超发坏点
-                nWhichBin = 0
-                for m in range(base_wind_and_power_count - 1):
-                    if DzMarch809[i, 0] > base_wind_and_power_df.loc[m, self.rated_wind_speed] and DzMarch809[i, 0] <= \
-                            base_wind_and_power_df.loc[m + 1, self.rated_wind_speed]:
-                        nWhichBin = m
-                        break
-
-                if nWhichBin > base_wind_and_power_count - 1 or nWhichBin == 0:
-                    continue
-
-                IdealPower = (DzMarch809[i, 0] - base_wind_and_power_df.loc[nWhichBin, self.rated_wind_speed]) / (
-                        base_wind_and_power_df.loc[nWhichBin + 1, self.rated_wind_speed] - base_wind_and_power_df.loc[
-                    nWhichBin, self.rated_wind_speed]) * (
-                                     base_wind_and_power_df.loc[nWhichBin + 1, self.rated_capacity] -
-                                     base_wind_and_power_df.loc[nWhichBin, self.rated_capacity]) + \
-                             base_wind_and_power_df.loc[nWhichBin, self.rated_capacity]
-
-                RemoveOverEP = RemoveOverEP + (DzMarch809[i, 1] - IdealPower) / 6
-                nType2 = nType2 + 1
-
-        print("RemoveOverEP", RemoveOverEP)
-        print("nType2", nType2)
-        # 额定功率以上的超发点
-        nTypeOver = 0
-        for i in range(nCounter1):
-            if DzMarch809[i, 1] > PRated:
-                RemoveOverEP = RemoveOverEP + (DzMarch809[i, 1] - PRated) / 6
-                nTypeOver = nTypeOver + 1
-
-        print("RemoveOverEP", RemoveOverEP)
-        print("nTypeOver", nTypeOver)
-
-    def run(self):
-        # Implement your class identification logic here
-        self.identifier()
-
-
-if __name__ == '__main__':
-    test = ClassIdentifier('test', r"D:\中能智能\matlib计算相关\好点坏点matlib计算\A01.csv", index='时间',
-                           wind_velocity='风速',
-                           active_power='功率')
-
-    test.run()

+ 1 - 2
tmp_file/ClassIdentifier_0.py → tmp_file/ClassIdentifier_1.py_bak

@@ -713,8 +713,7 @@ class ClassIdentifier(object):
             if Dzwind_and_power_dfSel[i] == 2:  # 功率主带左侧的超发坏点
                 nWhichBin = 0
                 for m in range(base_wind_and_power_count - 1):
-                    if DzMarch809[i, 0] > base_wind_and_power_df.loc[m, self.rated_wind_speed] and DzMarch809[i, 0] <= \
-                            base_wind_and_power_df.loc[m + 1, self.rated_wind_speed]:
+                    if base_wind_and_power_df.loc[m, self.rated_wind_speed] < DzMarch809[i, 0] <= base_wind_and_power_df.loc[m + 1, self.rated_wind_speed]:
                         nWhichBin = m
                         break
 

+ 0 - 371
tmp_file/ClassIdentifier_2.py

@@ -1,371 +0,0 @@
-import os
-
-import numpy as np
-from pandas import DataFrame
-
-from service.plt_service import get_base_wind_and_power
-from utils.draw.draw_file import scatter
-from utils.file.trans_methods import read_file_to_df
-
-
-class ClassIdentifier(object):
-
-    def __init__(self, wind_turbine_number, file_path: str = None, origin_df: DataFrame = None, index='time_stamp',
-                 wind_velocity='wind_velocity',
-                 active_power='active_power'):
-        """
-        :param wind_turbine_number: The wind turbine number.
-        :param file_path: The file path of the input data.
-        :param origin_df: The pandas DataFrame containing the input data.
-        :param index: 索引字段
-        :param wind_velocity: 风速字段
-        :param active_power: 有功功率字段
-        """
-        self.wind_turbine_number = wind_turbine_number
-        self.index = index
-        self.wind_velocity = wind_velocity
-        self.active_power = active_power
-
-        self.rated_wind_speed = 'rated_wind_speed'
-        self.rated_capacity = 'rated_capacity'
-
-        if file_path is None and origin_df is None:
-            raise ValueError("Either file_path or origin_df should be provided.")
-
-        if file_path:
-            self.df = read_file_to_df(file_path)
-        else:
-            self.df = origin_df
-
-        self.df = self.df.set_index(keys=self.index)
-
-    def identifier(self):
-        # 风速 和 有功功率 df
-        wind_and_power_df = self.df[[self.wind_velocity, self.active_power]]
-        wind_and_power_df.reset_index(inplace=True)
-        wind_and_power_df_count = wind_and_power_df.shape[0]
-        PowerMax = wind_and_power_df[self.active_power].max()
-        PowerRated = np.ceil(PowerMax / 100) * 100
-        PRated = 1500  # 额定功率1500kw,可改为2000kw
-        VCutOut = 25
-        # 网格法确定风速风向分区数量,功率方向分区数量,
-        # PNum = (PRated+100)/25  #功率分区间隔25kW
-        PNum = int(np.ceil(PowerRated / 25))  # 功率分区间隔25kW
-        VNum = int(np.ceil(VCutOut / 0.25))  # 风速分区间隔0.25m/s
-
-        # 存储功率大于零的运行数据
-        DzMarch809 = np.zeros([wind_and_power_df_count, 2], dtype=float)
-        nCounter1 = 0
-        for i in range(wind_and_power_df_count):
-            if wind_and_power_df.loc[i, self.active_power] > 0:
-                DzMarch809[nCounter1, 0] = wind_and_power_df.loc[i, self.wind_velocity]
-                DzMarch809[nCounter1, 1] = wind_and_power_df.loc[i, self.active_power]
-
-                nCounter1 = nCounter1 + 1
-
-        # 统计各网格落入的散点个数
-        if VNum == 1:
-            XBoxNumber = np.ones([PNum], dtype=int)
-        else:
-            XBoxNumber = np.ones([PNum, VNum], dtype=int)
-        nWhichP = -1
-        nWhichV = -1
-        for i in range(nCounter1):
-            for m in range(PNum):
-                if m * 25 < DzMarch809[i, 1] <= (m + 1) * 25:
-                    nWhichP = m
-                    break
-            for n in range(VNum):
-                if ((n + 1) * 0.25 - 0.125) < DzMarch809[i, 0] <= ((n + 1) * 0.25 + 0.125):
-                    nWhichV = n
-                    break
-
-            if nWhichP > -1 and nWhichV > -1:
-                XBoxNumber[nWhichP, nWhichV] = XBoxNumber[nWhichP, nWhichV] + 1
-
-        for m in range(PNum):
-            for n in range(VNum):
-                XBoxNumber[m, n] = XBoxNumber[m, n] - 1
-
-        # 在功率方向将网格内散点绝对个数转换为相对百分比,备用
-        PBoxPercent = np.zeros([PNum, VNum], dtype=float)
-        PBinSum = np.zeros(PNum, dtype=int)
-
-        for i in range(PNum):
-            for m in range(VNum):
-                PBinSum[i] = PBinSum[i] + XBoxNumber[i, m]
-
-            for m in range(VNum):
-                if PBinSum[i] > 0:
-                    PBoxPercent[i, m] = XBoxNumber[i, m] / PBinSum[i] * 100
-
-        # 在风速方向将网格内散点绝对个数转换为相对百分比,备用
-        VBoxPercent = np.zeros([PNum, VNum], dtype=float)
-        VBinSum = np.zeros(VNum, dtype=int)
-
-        for i in range(VNum):
-            for m in range(PNum):
-                VBinSum[i] = VBinSum[i] + XBoxNumber[m, i]
-
-            for m in range(PNum):
-                if VBinSum[i] > 0:
-                    VBoxPercent[m, i] = XBoxNumber[m, i] / VBinSum[i] * 100
-
-        # 以水平功率带方向为准,分析每个水平功率带中,功率主带中心,即找百分比最大的网格位置。
-        PBoxMaxIndex = np.zeros(PNum, dtype=int)  # 水平功率带最大网格位置索引
-        PBoxMaxP = np.zeros(PNum, dtype=int)  # 水平功率带最大网格百分比
-
-        for m in range(PNum):
-            # 确定每一水平功率带的最大网格位置索引即百分比值
-            PBoxMaxP[m], PBoxMaxIndex[m] = PBoxPercent[m, :].max(), PBoxPercent[m, :].argmax()
-
-        # 以垂直风速方向为准,分析每个垂直风速带中,功率主带中心,即找百分比最大的网格位置。
-        VBoxMaxIndex = np.zeros(VNum, dtype=int)
-        VBoxMaxV = np.zeros(VNum, dtype=int)
-
-        for m in range(VNum):
-            [VBoxMaxV[m], VBoxMaxIndex[m]] = VBoxPercent[:, m].max(), VBoxPercent[:, m].argmax()
-
-        # 切入风速特殊处理,如果切入风速过于偏右,向左拉回
-        if PBoxMaxIndex[0] > 14:
-            PBoxMaxIndex[0] = 9
-
-        # 以水平功率带方向为基准,进行分析
-        DotDense = np.zeros(PNum, dtype=int)  # 每一水平功率带的功率主带包含的网格数
-        DotDenseLeftRight = np.zeros([PNum, 2], dtype=int)  # 存储每一水平功率带的功率主带以最大网格为中心,向向左,向右扩展的网格数
-        DotValve = 90  # 从中心向左右对称扩展网格的散点百分比和的阈值。
-
-        for i in range(PNum - 6):  # 从最下层水平功率带1开始,向上到第PNum-6个水平功率带(额定功率一下水平功率带),逐一分析
-            PDotDenseSum = PBoxMaxP[i]  # 以中心最大水平功率带为基准,向左向右对称扩展网格,累加各网格散点百分比
-            iSpreadRight = 1
-            iSpreadLeft = 1
-            while PDotDenseSum < DotValve:
-
-                if (PBoxMaxIndex[i] + iSpreadRight) < VNum - 1:
-                    PDotDenseSum = PDotDenseSum + PBoxPercent[i, PBoxMaxIndex[i] + iSpreadRight]  # 向右侧扩展
-                    iSpreadRight = iSpreadRight + 1
-
-                if (PBoxMaxIndex[i] + iSpreadRight) > VNum - 1:
-                    break
-
-                if (PBoxMaxIndex[i] - iSpreadLeft) > 0:
-                    PDotDenseSum = PDotDenseSum + PBoxPercent[i, PBoxMaxIndex[i] - iSpreadLeft]  # 向左侧扩展
-                    iSpreadLeft = iSpreadLeft + 1
-
-                if (PBoxMaxIndex[i] - iSpreadLeft) <= 0:
-                    break
-
-            iSpreadRight = iSpreadRight - 1
-            iSpreadLeft = iSpreadLeft - 1
-            # 向左右对称扩展完毕
-
-            DotDenseLeftRight[i, 0] = iSpreadLeft
-            DotDenseLeftRight[i, 1] = iSpreadRight
-            DotDense[i] = iSpreadLeft + iSpreadRight + 1
-
-        # 各行功率主带右侧宽度的中位数最具有代表性
-        DotDenseWidthLeft = np.zeros([PNum - 6, 1], dtype=int)
-        for i in range(PNum - 6):
-            DotDenseWidthLeft[i] = DotDenseLeftRight[i, 1]
-
-        MainBandRight = np.median(DotDenseWidthLeft)
-
-        # 散点向右显著延展分布的水平功率带为限功率水平带
-        PowerLimit = np.zeros([PNum, 1], dtype=int)  # 各水平功率带是否为限功率标识,==1:是;==0:不是
-        WidthAverage = 0  # 功率主带平均宽度
-        WidthVar = 0  # 功率主带方差
-        # PowerLimitValve = 6    #限功率主带判别阈值
-        PowerLimitValve = np.ceil(MainBandRight) + 3  # 限功率主带判别阈值
-
-        nCounterLimit = 0
-        nCounter = 0
-
-        for i in range(PNum - 6):
-            if DotDenseLeftRight[i, 1] > PowerLimitValve and PBinSum[i] > 20:  # 如果向右扩展网格数大于阈值,且该水平功率带点总数>20,是
-                PowerLimit[i] = 1
-                nCounterLimit = nCounterLimit + 1
-
-            if DotDenseLeftRight[i, 1] <= PowerLimitValve:
-                WidthAverage = WidthAverage + DotDenseLeftRight[i, 1]  # 统计正常水平功率带右侧宽度
-                nCounter = nCounter + 1
-
-        WidthAverage = WidthAverage / nCounter  # 功率主带平均宽度
-
-        # 各水平功率带的功率主带宽度的方差,反映从下到上宽度是否一致,或是否下宽上窄等异常情况
-        for i in range(PNum - 6):
-            if DotDenseLeftRight[i, 1] <= PowerLimitValve:
-                WidthVar = WidthVar + (DotDenseLeftRight[i, 1] - WidthAverage) * (
-                        DotDenseLeftRight[i, 1] - WidthAverage)
-
-        # 对限负荷水平功率带的最大网格较下面相邻层显著偏右,拉回
-        for i in range(1, PNum - 6):
-            if PowerLimit[i] == 1 and abs(PBoxMaxIndex[i] - PBoxMaxIndex[i - 1]) > 5:
-                PBoxMaxIndex[i] = PBoxMaxIndex[i - 1] + 1
-
-        # 输出各层功率主带的左右边界网格索引
-        DotDenseInverse = np.zeros([PNum, 2], dtype=int)
-
-        for i in range(PNum):
-            DotDenseInverse[i, :] = DotDenseLeftRight[PNum - i - 1, :]
-
-        # 功率主带的右边界
-        CurveWidthR = int(np.ceil(WidthAverage) + 2)
-
-        # CurveWidthL = 6    #功率主带的左边界
-        CurveWidthL = CurveWidthR
-
-        BBoxLimit = np.zeros([PNum, VNum], dtype=int)  # 网格是否为限功率网格的标识,如果为限功率水平功率带,从功率主带右侧边缘向右的网格为限功率网格
-        for i in range(2, PNum - 6):
-            if PowerLimit[i] == 1:
-                for j in range(PBoxMaxIndex[i] + CurveWidthR, VNum):
-                    BBoxLimit[i, j] = 1
-
-        BBoxRemove = np.zeros([PNum, VNum], dtype=int)  # 数据异常需要剔除的网格标识,标识==1:功率主带右侧的欠发网格;==2:功率主带左侧的超发网格
-        for m in range(PNum - 6):
-            for n in range(PBoxMaxIndex[m] + CurveWidthR, VNum):
-                BBoxRemove[m, n] = 1
-
-            for n in range(PBoxMaxIndex[m] - CurveWidthL, -1, -1):
-                BBoxRemove[m, n] = 2
-
-        # 确定功率主带的左上拐点,即额定风速位置的网格索引
-        CurveTop = np.zeros(2, dtype=int)
-        CurveTopValve = 3  # 网格的百分比阈值
-        BTopFind = 0
-        for m in range(PNum - 4 - 1, -1, -1):
-            for n in range(VNum):
-                if VBoxPercent[m, n] > CurveTopValve and XBoxNumber[m, n] >= 10:  # 如左上角网格的百分比和散点个数大于阈值。
-                    CurveTop[0] = m
-                    CurveTop[1] = n
-                    BTopFind = 1
-                    break
-
-            if BTopFind == 1:
-                break
-
-        IsolateValve = 3
-        for m in range(PNum - 6):
-            for n in range(PBoxMaxIndex[m] + CurveWidthR, VNum):
-                if PBoxPercent[m, n] < IsolateValve:
-                    BBoxRemove[m, n] = 1
-
-        # 功率主带顶部宽度
-        CurveWidthT = 2
-        for m in range(PNum - CurveWidthT - 1, PNum):
-            for n in range(VNum):
-                BBoxRemove[m, n] = 3  # 网格为额定功率以上的超发点
-
-        # 功率主带拐点左侧的欠发网格标识
-        for m in range(PNum - 5 - 1, PNum):
-            for n in range(CurveTop[1] - 1):
-                BBoxRemove[m, n] = 2
-
-        # 以网格的标识,决定该网格内数据的标识。Dzwind_and_power_dfSel功率非零数据的标识位。散点在哪个网格,此网格的标识即为该点的标识
-        Dzwind_and_power_dfSel = np.zeros(nCounter1, dtype=int)  # -1:停机 0:好点  1:欠发功率点;2:超发功率点;3:额定风速以上的超发功率点 4: 限电
-        nWhichP = -1
-        nWhichV = -1
-        nBadA = 0
-
-        for i in range(nCounter1):
-            for m in range(PNum):
-                if m * 25 < DzMarch809[i, 1] <= (m + 1) * 25:
-                    nWhichP = m
-                    break
-
-            for n in range(VNum):
-                if ((n + 1) * 0.25 - 0.125) < DzMarch809[i, 0] <= ((n + 1) * 0.25 + 0.125):
-                    nWhichV = n
-                    break
-
-            if nWhichP > -1 and nWhichV > -1:
-
-                if BBoxRemove[nWhichP, nWhichV] == 1:
-                    Dzwind_and_power_dfSel[i] = 1
-                    nBadA = nBadA + 1
-
-                if BBoxRemove[nWhichP, nWhichV] == 2:
-                    Dzwind_and_power_dfSel[i] = 2
-
-                if BBoxRemove[nWhichP, nWhichV] == 3:
-                    Dzwind_and_power_dfSel[i] = 0  # 3  # 额定风速以上的超发功率点认为是正常点,不再标识。
-
-        # 限负荷数据标识方法2:把数据切割为若干个窗口。对每一窗口,以第一个点为基准,连续nWindowLength个数据的功率在方差范围内,呈现显著水平分布的点
-        nWindowLength = 3
-        LimitWindow = np.zeros(nWindowLength, dtype=float)
-        PowerStd = 15  # 功率波动方差
-        nWindowNum = int(np.floor(nCounter1 / nWindowLength))
-        PowerLimitUp = PRated - 300
-        PowerLimitLow = 200
-        for i in range(nWindowNum):
-            for j in range(nWindowLength):
-                LimitWindow[j] = DzMarch809[i * nWindowLength + j, 1]
-
-            bAllInAreas = 1
-            for j in range(nWindowLength):
-                if LimitWindow[j] < PowerLimitLow or LimitWindow[j] > PowerLimitUp:
-                    bAllInAreas = 0
-
-            if bAllInAreas == 0:
-                continue
-
-            UpLimit = LimitWindow[0] + PowerStd
-            LowLimit = LimitWindow[0] - PowerStd
-            bAllInUpLow = 1
-            for j in range(1, nWindowLength):
-                if LimitWindow[j] < LowLimit or LimitWindow[j] > UpLimit:
-                    bAllInUpLow = 0
-
-            if bAllInUpLow == 1:
-                for j in range(nWindowLength):
-                    Dzwind_and_power_dfSel[i * nWindowLength + j] = 4  # 标识窗口内的数据为限负荷数据
-
-        nSmooth = 0
-        for i in range(PNum - 6):
-            PVLeftDown = np.zeros(2, dtype=float)
-            PVRightUp = np.zeros(2, dtype=float)
-
-            if (PBoxMaxIndex[i + 1] - PBoxMaxIndex[i]) >= 1:
-                PVLeftDown[0] = (PBoxMaxIndex[i] + 1 + CurveWidthR) * 0.25 - 0.125
-                PVLeftDown[1] = i * 25
-
-                PVRightUp[0] = (PBoxMaxIndex[i + 1] + 1 + CurveWidthR) * 0.25 - 0.125
-                PVRightUp[1] = (i + 1) * 25
-
-                for m in range(nCounter1):
-                    if DzMarch809[m, 0] > PVLeftDown[0] and DzMarch809[m, 0] < PVRightUp[0] and PVLeftDown[1] < \
-                            DzMarch809[m, 1] < PVRightUp[1]:  # 在该锯齿中
-                        if (DzMarch809[m, 1] - PVLeftDown[1]) / (DzMarch809[m, 0] - PVLeftDown[0]) > (
-                                PVRightUp[1] - PVLeftDown[1]) / (
-                                PVRightUp[0] - PVLeftDown[0]):  # 斜率大于对角连线,则在锯齿左上三角形中,选中
-                            Dzwind_and_power_dfSel[m] = 0
-                            nSmooth = nSmooth + 1
-
-        print("nSmooth", nSmooth)
-
-        wind_and_power_df.loc[:, 'marker'] = -1
-        wind_and_power_df.loc[
-            wind_and_power_df[wind_and_power_df[self.active_power] > 0].index, 'marker'] = Dzwind_and_power_dfSel
-        wind_and_power_df.to_csv("test.csv", index=False, encoding='utf-8')
-
-        # wind_and_power_df = wind_and_power_df[wind_and_power_df['marker'] == 0]
-        color_map = {-1: 'red', 0: 'green', 1: 'blue', 2: 'black', 3: 'orange', 4: 'magenta'}
-        c = wind_and_power_df['marker'].map(color_map)
-
-        # -1:停机 0:好点  1:欠发功率点;2:超发功率点;3:额定风速以上的超发功率点 4: 限电
-        legend_map = {"停机": 'red', "好点": 'green', "欠发": 'blue', "超发": 'black', "额定风速以上的超发": 'orange', "限电": 'magenta'}
-
-        scatter("测试matlab结果", x_label='风速', y_label='有功功率', x_values=wind_and_power_df[self.wind_velocity].values,
-                y_values=wind_and_power_df[self.active_power].values, color=c, col_map=legend_map,
-                save_file_path=os.path.dirname(__file__) + os.sep + '测试matlab结果均值.png')
-
-    def run(self):
-        # Implement your class identification logic here
-        self.identifier()
-
-
-if __name__ == '__main__':
-    test = ClassIdentifier('test', r"D:\中能智能\matlib计算相关\好点坏点matlib计算\A01.csv", index='时间',
-                           wind_velocity='风速',
-                           active_power='功率')
-
-    test.run()

+ 0 - 389
tmp_file/ClassIdentifier_3.py

@@ -1,389 +0,0 @@
-import os
-
-import numpy as np
-from pandas import DataFrame
-
-from service.plt_service import get_base_wind_and_power
-from utils.draw.draw_file import scatter
-from utils.file.trans_methods import read_file_to_df
-
-
-class ClassIdentifier(object):
-
-    def __init__(self, wind_turbine_number, file_path: str = None, origin_df: DataFrame = None, index='time_stamp',
-                 wind_velocity='wind_velocity',
-                 active_power='active_power'):
-        """
-        :param wind_turbine_number: The wind turbine number.
-        :param file_path: The file path of the input data.
-        :param origin_df: The pandas DataFrame containing the input data.
-        :param index: 索引字段
-        :param wind_velocity: 风速字段
-        :param active_power: 有功功率字段
-        """
-        self.wind_turbine_number = wind_turbine_number
-        self.index = index
-        self.wind_velocity = wind_velocity
-        self.active_power = active_power
-
-        self.rated_wind_speed = 'rated_wind_speed'
-        self.rated_capacity = 'rated_capacity'
-
-        if file_path is None and origin_df is None:
-            raise ValueError("Either file_path or origin_df should be provided.")
-
-        if file_path:
-            self.df = read_file_to_df(file_path)
-        else:
-            self.df = origin_df
-
-        self.df = self.df.set_index(keys=self.index)
-
-    def identifier(self):
-        # 风速 和 有功功率 df
-        wind_and_power_df = self.df[[self.wind_velocity, self.active_power, "叶片角度"]]
-        wind_and_power_df.reset_index(inplace=True)
-        wind_and_power_df_count = wind_and_power_df.shape[0]
-        PowerMax = wind_and_power_df[self.active_power].max()
-        PowerRated = np.ceil(PowerMax / 100) * 100
-        PRated = 1500  # 额定功率1500kw,可改为2000kw
-        VCutOut = 25
-        # 网格法确定风速风向分区数量,功率方向分区数量,
-        # PNum = (PRated+100)/25  #功率分区间隔25kW
-        PNum = int(np.ceil(PowerRated / 25))  # 功率分区间隔25kW
-        VNum = int(np.ceil(VCutOut / 0.25))  # 风速分区间隔0.25m/s
-
-        # 存储功率大于零的运行数据
-        DzMarch809 = np.zeros([wind_and_power_df_count, 2], dtype=float)
-        nCounter1 = 0
-        for i in range(wind_and_power_df_count):
-            if wind_and_power_df.loc[i, self.active_power] > 0:
-                DzMarch809[nCounter1, 0] = wind_and_power_df.loc[i, self.wind_velocity]
-                DzMarch809[nCounter1, 1] = wind_and_power_df.loc[i, self.active_power]
-
-                nCounter1 = nCounter1 + 1
-
-        # 统计各网格落入的散点个数
-        if VNum == 1:
-            XBoxNumber = np.ones([PNum], dtype=int)
-        else:
-            XBoxNumber = np.ones([PNum, VNum], dtype=int)
-        nWhichP = -1
-        nWhichV = -1
-        for i in range(nCounter1):
-            for m in range(PNum):
-                if m * 25 < DzMarch809[i, 1] <= (m + 1) * 25:
-                    nWhichP = m
-                    break
-            for n in range(VNum):
-                if ((n + 1) * 0.25 - 0.125) < DzMarch809[i, 0] <= ((n + 1) * 0.25 + 0.125):
-                    nWhichV = n
-                    break
-
-            if nWhichP > -1 and nWhichV > -1:
-                XBoxNumber[nWhichP, nWhichV] = XBoxNumber[nWhichP, nWhichV] + 1
-
-        for m in range(PNum):
-            for n in range(VNum):
-                XBoxNumber[m, n] = XBoxNumber[m, n] - 1
-
-        # 在功率方向将网格内散点绝对个数转换为相对百分比,备用
-        PBoxPercent = np.zeros([PNum, VNum], dtype=float)
-        PBinSum = np.zeros(PNum, dtype=int)
-
-        for i in range(PNum):
-            for m in range(VNum):
-                PBinSum[i] = PBinSum[i] + XBoxNumber[i, m]
-
-            for m in range(VNum):
-                if PBinSum[i] > 0:
-                    PBoxPercent[i, m] = XBoxNumber[i, m] / PBinSum[i] * 100
-
-        # 在风速方向将网格内散点绝对个数转换为相对百分比,备用
-        VBoxPercent = np.zeros([PNum, VNum], dtype=float)
-        VBinSum = np.zeros(VNum, dtype=int)
-
-        for i in range(VNum):
-            for m in range(PNum):
-                VBinSum[i] = VBinSum[i] + XBoxNumber[m, i]
-
-            for m in range(PNum):
-                if VBinSum[i] > 0:
-                    VBoxPercent[m, i] = XBoxNumber[m, i] / VBinSum[i] * 100
-
-        # 以水平功率带方向为准,分析每个水平功率带中,功率主带中心,即找百分比最大的网格位置。
-        PBoxMaxIndex = np.zeros(PNum, dtype=int)  # 水平功率带最大网格位置索引
-        PBoxMaxP = np.zeros(PNum, dtype=int)  # 水平功率带最大网格百分比
-
-        for m in range(PNum):
-            # 确定每一水平功率带的最大网格位置索引即百分比值
-            PBoxMaxP[m], PBoxMaxIndex[m] = PBoxPercent[m, :].max(), PBoxPercent[m, :].argmax()
-
-        # 以垂直风速方向为准,分析每个垂直风速带中,功率主带中心,即找百分比最大的网格位置。
-        VBoxMaxIndex = np.zeros(VNum, dtype=int)
-        VBoxMaxV = np.zeros(VNum, dtype=int)
-
-        for m in range(VNum):
-            [VBoxMaxV[m], VBoxMaxIndex[m]] = VBoxPercent[:, m].max(), VBoxPercent[:, m].argmax()
-
-        # 切入风速特殊处理,如果切入风速过于偏右,向左拉回
-        if PBoxMaxIndex[0] > 14:
-            PBoxMaxIndex[0] = 9
-
-        # 以水平功率带方向为基准,进行分析
-        DotDense = np.zeros(PNum, dtype=int)  # 每一水平功率带的功率主带包含的网格数
-        DotDenseLeftRight = np.zeros([PNum, 2], dtype=int)  # 存储每一水平功率带的功率主带以最大网格为中心,向向左,向右扩展的网格数
-        DotValve = 90  # 从中心向左右对称扩展网格的散点百分比和的阈值。
-
-        for i in range(PNum - 6):  # 从最下层水平功率带1开始,向上到第PNum-6个水平功率带(额定功率一下水平功率带),逐一分析
-            PDotDenseSum = PBoxMaxP[i]  # 以中心最大水平功率带为基准,向左向右对称扩展网格,累加各网格散点百分比
-            iSpreadRight = 1
-            iSpreadLeft = 1
-            while PDotDenseSum < DotValve:
-
-                if (PBoxMaxIndex[i] + iSpreadRight) < VNum - 1:
-                    PDotDenseSum = PDotDenseSum + PBoxPercent[i, PBoxMaxIndex[i] + iSpreadRight]  # 向右侧扩展
-                    iSpreadRight = iSpreadRight + 1
-
-                if (PBoxMaxIndex[i] + iSpreadRight) > VNum - 1:
-                    break
-
-                if (PBoxMaxIndex[i] - iSpreadLeft) > 0:
-                    PDotDenseSum = PDotDenseSum + PBoxPercent[i, PBoxMaxIndex[i] - iSpreadLeft]  # 向左侧扩展
-                    iSpreadLeft = iSpreadLeft + 1
-
-                if (PBoxMaxIndex[i] - iSpreadLeft) <= 0:
-                    break
-
-            iSpreadRight = iSpreadRight - 1
-            iSpreadLeft = iSpreadLeft - 1
-            # 向左右对称扩展完毕
-
-            DotDenseLeftRight[i, 0] = iSpreadLeft
-            DotDenseLeftRight[i, 1] = iSpreadRight
-            DotDense[i] = iSpreadLeft + iSpreadRight + 1
-
-        # 各行功率主带右侧宽度的中位数最具有代表性
-        DotDenseWidthLeft = np.zeros([PNum - 6, 1], dtype=int)
-        for i in range(PNum - 6):
-            DotDenseWidthLeft[i] = DotDenseLeftRight[i, 1]
-
-        MainBandRight = np.median(DotDenseWidthLeft)
-
-        # 散点向右显著延展分布的水平功率带为限功率水平带
-        PowerLimit = np.zeros([PNum, 1], dtype=int)  # 各水平功率带是否为限功率标识,==1:是;==0:不是
-        WidthAverage = 0  # 功率主带平均宽度
-        WidthVar = 0  # 功率主带方差
-        # PowerLimitValve = 6    #限功率主带判别阈值
-        PowerLimitValve = np.ceil(MainBandRight) + 3  # 限功率主带判别阈值
-
-        nCounterLimit = 0
-        nCounter = 0
-
-        for i in range(PNum - 6):
-            if DotDenseLeftRight[i, 1] > PowerLimitValve and PBinSum[i] > 20:  # 如果向右扩展网格数大于阈值,且该水平功率带点总数>20,是
-                PowerLimit[i] = 1
-                nCounterLimit = nCounterLimit + 1
-
-            if DotDenseLeftRight[i, 1] <= PowerLimitValve:
-                WidthAverage = WidthAverage + DotDenseLeftRight[i, 1]  # 统计正常水平功率带右侧宽度
-                nCounter = nCounter + 1
-
-        WidthAverage = WidthAverage / nCounter  # 功率主带平均宽度
-
-        # 各水平功率带的功率主带宽度的方差,反映从下到上宽度是否一致,或是否下宽上窄等异常情况
-        for i in range(PNum - 6):
-            if DotDenseLeftRight[i, 1] <= PowerLimitValve:
-                WidthVar = WidthVar + (DotDenseLeftRight[i, 1] - WidthAverage) * (
-                        DotDenseLeftRight[i, 1] - WidthAverage)
-
-        # 对限负荷水平功率带的最大网格较下面相邻层显著偏右,拉回
-        for i in range(1, PNum - 6):
-            if PowerLimit[i] == 1 and abs(PBoxMaxIndex[i] - PBoxMaxIndex[i - 1]) > 5:
-                PBoxMaxIndex[i] = PBoxMaxIndex[i - 1] + 1
-
-        # 输出各层功率主带的左右边界网格索引
-        DotDenseInverse = np.zeros([PNum, 2], dtype=int)
-
-        for i in range(PNum):
-            DotDenseInverse[i, :] = DotDenseLeftRight[PNum - i - 1, :]
-
-        # 功率主带的右边界
-        CurveWidthR = int(np.ceil(WidthAverage) + 2)
-
-        # CurveWidthL = 6    #功率主带的左边界
-        CurveWidthL = CurveWidthR
-
-        BBoxLimit = np.zeros([PNum, VNum], dtype=int)  # 网格是否为限功率网格的标识,如果为限功率水平功率带,从功率主带右侧边缘向右的网格为限功率网格
-        for i in range(2, PNum - 6):
-            if PowerLimit[i] == 1:
-                for j in range(PBoxMaxIndex[i] + CurveWidthR, VNum):
-                    BBoxLimit[i, j] = 1
-
-        BBoxRemove = np.zeros([PNum, VNum], dtype=int)  # 数据异常需要剔除的网格标识,标识==1:功率主带右侧的欠发网格;==2:功率主带左侧的超发网格
-        for m in range(PNum - 6):
-            for n in range(PBoxMaxIndex[m] + CurveWidthR, VNum):
-                BBoxRemove[m, n] = 1
-
-            for n in range(PBoxMaxIndex[m] - CurveWidthL, -1, -1):
-                BBoxRemove[m, n] = 2
-
-        # 确定功率主带的左上拐点,即额定风速位置的网格索引
-        CurveTop = np.zeros(2, dtype=int)
-        CurveTopValve = 3  # 网格的百分比阈值
-        BTopFind = 0
-        for m in range(PNum - 4 - 1, -1, -1):
-            for n in range(VNum):
-                if VBoxPercent[m, n] > CurveTopValve and XBoxNumber[m, n] >= 10:  # 如左上角网格的百分比和散点个数大于阈值。
-                    CurveTop[0] = m
-                    CurveTop[1] = n
-                    BTopFind = 1
-                    break
-
-            if BTopFind == 1:
-                break
-
-        IsolateValve = 3
-        for m in range(PNum - 6):
-            for n in range(PBoxMaxIndex[m] + CurveWidthR, VNum):
-                if PBoxPercent[m, n] < IsolateValve:
-                    BBoxRemove[m, n] = 1
-
-        # 功率主带顶部宽度
-        CurveWidthT = 2
-        for m in range(PNum - CurveWidthT - 1, PNum):
-            for n in range(VNum):
-                BBoxRemove[m, n] = 3  # 网格为额定功率以上的超发点
-
-        # 功率主带拐点左侧的欠发网格标识
-        for m in range(PNum - 5 - 1, PNum):
-            for n in range(CurveTop[1] - 1):
-                BBoxRemove[m, n] = 2
-
-        # 以网格的标识,决定该网格内数据的标识。Dzwind_and_power_dfSel功率非零数据的标识位。散点在哪个网格,此网格的标识即为该点的标识
-        Dzwind_and_power_dfSel = np.zeros(nCounter1, dtype=int)  # -1:停机 0:好点  1:欠发功率点;2:超发功率点;3:额定风速以上的超发功率点 4: 限电
-        nWhichP = -1
-        nWhichV = -1
-        nBadA = 0
-
-        for i in range(nCounter1):
-            for m in range(PNum):
-                if m * 25 < DzMarch809[i, 1] <= (m + 1) * 25:
-                    nWhichP = m
-                    break
-
-            for n in range(VNum):
-                if ((n + 1) * 0.25 - 0.125) < DzMarch809[i, 0] <= ((n + 1) * 0.25 + 0.125):
-                    nWhichV = n
-                    break
-
-            if nWhichP > -1 and nWhichV > -1:
-
-                if BBoxRemove[nWhichP, nWhichV] == 1:
-                    Dzwind_and_power_dfSel[i] = 1
-                    nBadA = nBadA + 1
-
-                if BBoxRemove[nWhichP, nWhichV] == 2:
-                    Dzwind_and_power_dfSel[i] = 2
-
-                if BBoxRemove[nWhichP, nWhichV] == 3:
-                    Dzwind_and_power_dfSel[i] = 0  # 3  # 额定风速以上的超发功率点认为是正常点,不再标识。
-
-        # 限负荷数据标识方法2:把数据切割为若干个窗口。对每一窗口,以第一个点为基准,连续nWindowLength个数据的功率在方差范围内,呈现显著水平分布的点
-        nWindowLength = 3
-        LimitWindow = np.zeros(nWindowLength, dtype=float)
-        PowerStd = 15  # 功率波动方差
-        nWindowNum = int(np.floor(nCounter1 / nWindowLength))
-        PowerLimitUp = PRated - 300
-        PowerLimitLow = 200
-        for i in range(nWindowNum):
-            for j in range(nWindowLength):
-                LimitWindow[j] = DzMarch809[i * nWindowLength + j, 1]
-
-            bAllInAreas = 1
-            for j in range(nWindowLength):
-                if LimitWindow[j] < PowerLimitLow or LimitWindow[j] > PowerLimitUp:
-                    bAllInAreas = 0
-
-            if bAllInAreas == 0:
-                continue
-
-            UpLimit = LimitWindow[0] + PowerStd
-            LowLimit = LimitWindow[0] - PowerStd
-            bAllInUpLow = 1
-            for j in range(1, nWindowLength):
-                if LimitWindow[j] < LowLimit or LimitWindow[j] > UpLimit:
-                    bAllInUpLow = 0
-
-            if bAllInUpLow == 1:
-                for j in range(nWindowLength):
-                    Dzwind_and_power_dfSel[i * nWindowLength + j] = 4  # 标识窗口内的数据为限负荷数据
-
-        nSmooth = 0
-        for i in range(PNum - 6):
-            PVLeftDown = np.zeros(2, dtype=float)
-            PVRightUp = np.zeros(2, dtype=float)
-
-            if (PBoxMaxIndex[i + 1] - PBoxMaxIndex[i]) >= 1:
-                PVLeftDown[0] = (PBoxMaxIndex[i] + 1 + CurveWidthR) * 0.25 - 0.125
-                PVLeftDown[1] = i * 25
-
-                PVRightUp[0] = (PBoxMaxIndex[i + 1] + 1 + CurveWidthR) * 0.25 - 0.125
-                PVRightUp[1] = (i + 1) * 25
-
-                for m in range(nCounter1):
-                    if DzMarch809[m, 0] > PVLeftDown[0] and DzMarch809[m, 0] < PVRightUp[0] and PVLeftDown[1] < \
-                            DzMarch809[m, 1] < PVRightUp[1]:  # 在该锯齿中
-                        if (DzMarch809[m, 1] - PVLeftDown[1]) / (DzMarch809[m, 0] - PVLeftDown[0]) > (
-                                PVRightUp[1] - PVLeftDown[1]) / (
-                                PVRightUp[0] - PVLeftDown[0]):  # 斜率大于对角连线,则在锯齿左上三角形中,选中
-                            Dzwind_and_power_dfSel[m] = 0
-                            nSmooth = nSmooth + 1
-
-        print("nSmooth", nSmooth)
-
-        wind_and_power_df.loc[:, 'marker'] = -1
-        wind_and_power_df.loc[
-            wind_and_power_df[wind_and_power_df[self.active_power] > 0].index, 'marker'] = Dzwind_and_power_dfSel
-
-        # 把部分欠发的优化为限电
-        # 假设self.active_power已经被定义为DataFrame中的一个列名,这里用'有功功率'代替
-
-        # 构建条件表达式
-        cond1 = (wind_and_power_df['marker'] == 1) & (
-                (wind_and_power_df[self.active_power] < 1100) & (wind_and_power_df['叶片角度'] > 0.5)
-        )
-        cond2 = (wind_and_power_df['marker'] == 1) & (
-                (wind_and_power_df[self.active_power] < 1250) & (wind_and_power_df['叶片角度'] > 1.5)
-        )
-        cond3 = (wind_and_power_df['marker'] == 1) & (
-                (wind_and_power_df[self.active_power] < 1400) & (wind_and_power_df['叶片角度'] > 2.5)
-        )
-
-        # 使用逻辑或操作符|合并条件
-        combined_condition = cond1 | cond2 | cond3
-
-        # 更新满足条件的行的'marker'列
-        wind_and_power_df.loc[combined_condition, 'marker'] = 4
-
-        color_map = {-1: 'red', 0: 'green', 1: 'blue', 2: 'black', 3: 'orange', 4: 'magenta'}
-        c = wind_and_power_df['marker'].map(color_map)
-
-        # -1:停机 0:好点  1:欠发功率点;2:超发功率点;3:额定风速以上的超发功率点 4: 限电
-        legend_map = {"停机": 'red', "好点": 'green', "欠发": 'blue', "超发": 'black', "额定风速以上的超发": 'orange', "限电": 'magenta'}
-
-        scatter("测试matlab结果", x_label='风速', y_label='有功功率', x_values=wind_and_power_df[self.wind_velocity].values,
-                y_values=wind_and_power_df[self.active_power].values, color=c, col_map=legend_map,
-                save_file_path=os.path.dirname(__file__) + os.sep + '平陆测试matlab结果均值.png')
-
-    def run(self):
-        # Implement your class identification logic here
-        self.identifier()
-
-
-if __name__ == '__main__':
-    test = ClassIdentifier('test', r"D:\中能智能\matlib计算相关\好点坏点matlib计算\A01.csv", index='时间',
-                           wind_velocity='风速',
-                           active_power='功率')
-
-    test.run()

+ 12 - 4
tmp_file/read_and_draw_png.py

@@ -1,6 +1,7 @@
 import multiprocessing
 import os
 
+from etl.step.ClassIdentifier import ClassIdentifier
 from utils.draw.draw_file import scatter
 from utils.file.trans_methods import read_file_to_df
 
@@ -8,6 +9,10 @@ from utils.file.trans_methods import read_file_to_df
 def draw(file, fengchang='测试'):
     name = os.path.basename(file).split('.')[0]
     df = read_file_to_df(file)
+
+    identifier = ClassIdentifier(wind_turbine_number='test', origin_df=df, rated_power=1500, cut_out_speed=25,active_power='功率',wind_velocity='风速')
+    df = identifier.run()
+
     df.loc[df['active_power'] <= 0, 'lab'] = -1
 
     color_map = {-1: 'red', 0: 'green', 1: 'blue', 2: 'black', 3: 'orange', 4: 'magenta'}
@@ -18,13 +23,16 @@ def draw(file, fengchang='测试'):
     scatter(name, x_label='风速', y_label='有功功率', x_values=df['wind_velocity'].values,
             y_values=df['active_power'].values, color=c, col_map=legend_map,
             save_file_path=os.path.dirname(
-                    os.path.dirname(__file__)) + os.sep + "tmp" + os.sep + str(fengchang) + os.sep + name + '结果.png')
+                os.path.dirname(__file__)) + os.sep + "tmp" + os.sep + str(fengchang) + os.sep + name + '结果.png')
 
 
 if __name__ == '__main__':
-    read_dir = r"D:\data\清理数据\和风元宝山\test_11_test\minute"
+    read_dir = r"D:\data\清理数据\和风元宝山\test_11_test\test_A01"
 
     files = [read_dir + os.sep + i for i in os.listdir(read_dir)]
 
-    with multiprocessing.Pool(6) as pool:
-        pool.starmap(draw, [(file, "和风元宝山") for file in files])
+    if len(files) == 1:
+        draw(files[0], "和风元宝山4")
+    else:
+        with multiprocessing.Pool(4) as pool:
+            pool.starmap(draw, [(file, "和风元宝山4") for file in files])

+ 16 - 0
utils/df_utils/util.py

@@ -30,6 +30,19 @@ def get_time_space_count(start_time: datetime.datetime, end_time: datetime.datet
     return int(total_seconds / time_space) + 1
 
 
+def calculate_time_difference(now: datetime.datetime, date: datetime.datetime):
+    # 计算时间差
+    delta = now - date
+
+    # 分解timedelta对象
+    years, days = divmod(delta.days, 365)
+    months, days = divmod(days, 30)  # 这里假设一个月有30天
+    hours, remainder = divmod(delta.seconds, 3600)
+    minutes, seconds = divmod(remainder, 60)
+
+    return years, months, days, hours, minutes, seconds
+
+
 if __name__ == '__main__':
     df = pd.read_csv(r"D:\trans_data\01.csv")
     df['time_stamp'] = pd.to_datetime(df['time_stamp'])
@@ -39,3 +52,6 @@ if __name__ == '__main__':
     result = get_time_space_count(min, max, space)
     print(df.shape)
     print(space, min, max, result)
+
+    year, monht, day, _, _, _ = calculate_time_difference(datetime.datetime.now(), max)
+    print(f"{year}年{monht}月{day}天")