Xmia 1 тиждень тому
батько
коміт
cef771089f

+ 1 - 1
dataAnalysisBusiness/algorithm/powerCurveAnalyst.py

@@ -159,7 +159,7 @@ class PowerCurveAnalyst(AnalystWithGoodPoint):
     #                         'EffectiveQuantity', Field_ActiverPower]
     #     return act_line
 
-def buildPowerCurveData(self, group: pd.DataFrame, fieldWindSpeed: str, fieldActivePower: str, bins) -> pd.DataFrame:
+    def buildPowerCurveData(self, group: pd.DataFrame, fieldWindSpeed: str, fieldActivePower: str, bins) -> pd.DataFrame:
         """
         计算设备的功率曲线。
         """

+ 29 - 10
dataAnalysisBusiness/algorithm/yawErrorDensityAnalyst.py

@@ -72,20 +72,28 @@ class YawErrorDensityAnalyst(AnalystWithGoodBadLimitPoint):
             # yawerror=np.mean(dataFrame[Field_YawError])
 
             df = self.calculateYawError(group)
+            
+            # 这里的 dropna 会修改 df
             df.dropna(inplace=True)
             
-            # 如果返回的是空的,跳过
+            # 1. 之前加的防护:如果是空的,跳过
             if df.empty:
-                print(f"Warning: Turbine {name[0]} has no valid data after screening, skip the analysis.")
+                # print(f"Warning: Turbine {name[0]} has no valid data after screening, skip the analysis.")
                 continue
             
             counts = df['density'].value_counts()
             count_0 = counts.get(0, 0)  # 获取 density 为 0 的数量,如果没有 0 则返回 0
             count_1 = counts.get(1, 0)  # 获取 density 为 1 的数量,如果没有 1 则返回 0
 
-            # print(f"Density 为 0 的数量: {count_0}")
-            # print(f"Density 为 1 的数量: {count_1}")
+            # 2. 这里的筛选可能再次导致 df 变空
             df = df[df["density"]>0]
+
+            # 【重要】再次检查是否为空,或者数据量太少
+            # KDE 至少需要 2 个点才能计算,且方差不能为 0
+            if df.empty or len(df) < 2:
+                 # print(f"Warning: Turbine {name[0]} has insufficient data for density plot.")
+                 continue
+
             mean_X = np.mean(df["x"])
             std_X = np.std(df["x"])
             mediann_X= np.median(df["x"])
@@ -104,7 +112,7 @@ class YawErrorDensityAnalyst(AnalystWithGoodBadLimitPoint):
             }
             result = pd.DataFrame(result)
 
-            # 用密度作为颜色绘制散点图,并限制横坐标范围为 -20 到 20
+            # 用密度作为颜色绘制散点图
             fig = go.Figure()
             fig.add_trace(go.Scattergl(
                 x=df["x"],
@@ -154,10 +162,21 @@ class YawErrorDensityAnalyst(AnalystWithGoodBadLimitPoint):
             }]
             }
 
-            # 使用 gaussian_kde 估计数据的概率密度函数
-            kde = gaussian_kde(df["x"])
-            x = np.linspace(-30, 30, 1000)  # 生成 x 轴数据
-            pdf_data = kde(x)  # 数据的概率密度函数
+            x_range = np.linspace(-30, 30, 1000)  # 先定义 x 轴
+            try:
+                # 尝试计算 KDE
+                # 要求:数据点 > 1 且 方差 != 0
+                if df["x"].nunique() > 1: 
+                    kde = gaussian_kde(df["x"])
+                    pdf_data = kde(x_range)
+                else:
+                    # 如果所有数据都一样(方差为0),KDE 无法计算
+                    # 直接给 0 或者抛出异常进入 except
+                    raise ValueError("Data variance is zero")
+            except Exception as e:
+                # print(f"KDE calculation failed for {name[0]}: {e}. Using zero distribution.")
+                # 如果失败,生成全 0 的平直线,保证 JSON 结构完整
+                pdf_data = np.zeros_like(x_range)
 
             # 构建最终的JSON对象2
             json_output2 = {
@@ -170,7 +189,7 @@ class YawErrorDensityAnalyst(AnalystWithGoodBadLimitPoint):
                 "engineName": name[0],
                 "engineCode": name[1],
                 "title":f'概率密度函数-{name[0]}',
-                "xData": x .tolist(),
+                "xData": x_range.tolist(),
                 "yData": pdf_data.tolist(),
                 "xrange":[-30,30]