| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import pandas as pd
- import os
- from algorithmContract.confBusiness import *
- from algorithmContract.contract import Contract
- from behavior.analystNotFilter import AnalystNotFilter
- class FaultAnalyst(AnalystNotFilter):
- """
- 风电机组故障分析
- 新逻辑:基于首发故障结束时间划分窗口, 以首发故障的结束时间为界,后续故障的开始时间如果 ≤ 这个结束时间,则视为连带故障;否则作为新的首发故障。
- 风场范围的故障分析
- 统计风场范围内 首发故障中各故障发生的次数和累计时长
- """
- def typeAnalyst(self):
- return "fault"
- def selectColumns(self):
- # 直接返回数据库表中的真实列名
- return ["wind_turbine_name", "begin_time", "end_time", "fault_detail"]
- #风机原始名称、故障开始时间、故障结束时间、故障描述
- def getTimeGranularitys(self, conf: Contract):
- return ["fault"]
- def turbinesAnalysis(self, outputAnalysisDir, conf: Contract, turbineCodes):
- dictionary = self.processTurbineData(turbineCodes, conf, self.selectColumns())
- dataFrameMerge = dictionary.get("fault", pd.DataFrame())
- if dataFrameMerge.empty:
- return pd.DataFrame()
- return self.get_result(dataFrameMerge, outputAnalysisDir, conf)
- def get_result(self, dataFrame: pd.DataFrame, outputAnalysisDir: str, conf: Contract):
- if dataFrame.empty:
- return pd.DataFrame()
- df = dataFrame.copy()
-
- # 转换时间列
- df["begin_time"] = pd.to_datetime(df["begin_time"])
- df["end_time"] = pd.to_datetime(df["end_time"])
- df = df.dropna(subset=["begin_time", "end_time"])
- if df.empty:
- return pd.DataFrame()
- # 存储中间结果
- turbine_events = []
- fault_events = []
- # 按风机分组处理
- for turbine, group in df.groupby("wind_turbine_name"):
- group = group.sort_values("begin_time").reset_index(drop=True)
- i = 0
- n = len(group)
- while i < n:
- primary = group.iloc[i]
- primary_start = primary["begin_time"]
- primary_end = primary["end_time"]
- duration_sec = (primary_end - primary_start).total_seconds()
- turbine_events.append({
- "turbine": turbine,
- "duration_sec": duration_sec
- })
- fault_events.append({
- "fault_detail": primary["fault_detail"],
- "duration_sec": duration_sec
- })
- # 跳过连带故障
- j = i + 1
- while j < n and group.iloc[j]["begin_time"] <= primary_end:
- j += 1
- i = j
- # 聚合风机维度
- if turbine_events:
- turbine_df = pd.DataFrame(turbine_events)
- turbine_summary = turbine_df.groupby("turbine").agg(
- count=("duration_sec", "size"),
- fault_time=("duration_sec", "sum")
- ).reset_index()
- turbine_summary = turbine_summary.rename(columns={"turbine": "wind_turbine_name"})
- turbine_file = os.path.join(outputAnalysisDir, f"turbine_fault_result{CSVSuffix}")
- turbine_summary.to_csv(turbine_file, index=False, encoding='utf-8-sig')
- else:
- turbine_summary = pd.DataFrame()
- # 聚合故障类型维度
- if fault_events:
- fault_df = pd.DataFrame(fault_events)
- fault_summary = fault_df.groupby("fault_detail").agg(
- count=("duration_sec", "size"),
- fault_time_sum=("duration_sec", "sum")
- ).reset_index()
- fault_file = os.path.join(outputAnalysisDir, f"total_fault_result{CSVSuffix}")
- fault_summary.to_csv(fault_file, index=False, encoding='utf-8-sig')
- else:
- fault_summary = pd.DataFrame()
- # 返回结果
- result_rows = []
- if not turbine_summary.empty:
- result_rows.append({
- Field_Return_TypeAnalyst: self.typeAnalyst(),
- Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
- Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
- Field_CodeOfTurbine: "total",
- Field_MillTypeCode: "turbine_fault_result",
- Field_Return_FilePath: turbine_file,
- Field_Return_IsSaveDatabase: True
- })
- if not fault_summary.empty:
- result_rows.append({
- Field_Return_TypeAnalyst: self.typeAnalyst(),
- Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
- Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
- Field_CodeOfTurbine: "total",
- Field_MillTypeCode: "total_fault_result",
- Field_Return_FilePath: fault_file,
- Field_Return_IsSaveDatabase: True
- })
- return pd.DataFrame(result_rows)
|