cell_outlier.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import pandas as pd
  2. import pdb
  3. from sklearn.ensemble import IsolationForest
  4. import numpy as np
  5. # 计算充电过程
  6. def preprocess(df):
  7. # 滤除前后电压存在一增一减的情况(采样异常)
  8. pass
  9. # 计算电压的偏离度
  10. def cal_volt_uniform(dfin, volt_column, window=10, step=5, threshold=3):
  11. df = dfin.copy()
  12. time_list = dfin['time'].tolist()
  13. # 电压滤波
  14. df_volt = df[volt_column]
  15. df_volt_rolling = df_volt.rolling(window).mean()[window-1::step] # 滑动平均值
  16. time_list = time_list[window-1::step]
  17. # 电压偏离度
  18. mean = df_volt_rolling.mean(axis=1)
  19. std = df_volt_rolling.std(axis=1)
  20. df_volt_rolling_norm = df_volt_rolling.sub(mean, axis=0).div(std,axis=0)
  21. df_volt_rolling_norm = df_volt_rolling_norm.reset_index(drop=True)
  22. return df_volt_rolling_norm, time_list
  23. # 计算电压变化量的偏离度
  24. def cal_voltdiff_uniform(dfin, volt_column, window=10, step=5, window2=10, step2=5,threshold=3):
  25. df = dfin.copy()
  26. time_list = dfin['time'].tolist()
  27. # 电压滤波
  28. df_volt = df[volt_column]
  29. df_volt_rolling = df_volt.rolling(window).mean()[window-1::step] # 滑动平均值
  30. time_list = time_list[window-1::step]
  31. # 计算电压变化量的绝对值(# 计算前后的差值的绝对值, 时间列-1)
  32. df_volt_diff = abs(df_volt_rolling.diff()[1:])
  33. df_volt_diff = df_volt_diff.reset_index(drop=True)
  34. time_list = time_list[1:]
  35. # 压差归一化(偏离度)
  36. # mean = df_volt_diff.mean(axis=1)
  37. # std = df_volt_diff.std(axis=1)
  38. # df_voltdiff_norm = df_volt_diff.sub(mean, axis=0).div(std,axis=0)
  39. df_voltdiff_norm = df_volt_diff.copy()
  40. # 压差偏离度滑动平均滤波
  41. df_voltdiff_rolling = df_voltdiff_norm.rolling(window2).mean()[window2-1::step2] # 滑动平均值
  42. time_list = time_list[window2-1::step2]
  43. mean = df_voltdiff_rolling.mean(axis=1)
  44. std = df_voltdiff_rolling.std(axis=1)
  45. df_voltdiff_rolling_norm = df_voltdiff_rolling.sub(mean, axis=0).div(std,axis=0)
  46. df_voltdiff_rolling_norm = df_voltdiff_rolling_norm.reset_index(drop=True)
  47. return df_voltdiff_rolling_norm, time_list
  48. # this_alarm = {}
  49. # df_alarm = df_voltdiff_rolling_norm[abs(df_voltdiff_rolling_norm)>threshold].dropna(how='all')
  50. # for index in df_alarm.index:
  51. # df_temp = df_alarm.loc[index, :].dropna(how='all', axis=0)
  52. # this_alarm.update({df_cell_volt.loc[index+1, 'date']:[str(df_temp.keys().tolist()), str([round(x, 2) for x in df_temp.values.tolist()])]})
  53. # df_alarm1 = pd.DataFrame(this_alarm)
  54. # return pd.DataFrame(df_alarm1.values.T, index=df_alarm1.columns, columns=df_alarm1.index), pd.DataFrame(df_alarm2.values.T, index=df_alarm2.columns, columns=df_alarm2.index)
  55. # 孤立森林算法
  56. def iso_froest(df):
  57. #1. 生成训练数据
  58. rng = np.random.RandomState(42)
  59. X = 0.3 * rng.randn(100, 2) #生成100 行,2 列
  60. X_train = np.r_[X + 2, X - 2]
  61. print(X_train)
  62. # 产生一些异常数据
  63. X_outliers = rng.uniform(low=-4, high=4, size=(20, 2))
  64. iForest= IsolationForest(contamination=0.1)
  65. iForest = iForest.fit(X_train)
  66. #预测
  67. pred = iForest.predict(X_outliers)
  68. print(pred)
  69. # [-1 1 -1 -1 -1 -1 -1 1 -
  70. # 计算相关系数
  71. def cal_coff(df):
  72. cc_mean = np.mean(df, axis=0) #axis=0,表示按列求均值 ——— 即第一维
  73. cc_std = np.std(df, axis=0)
  74. cc_zscore = (df-cc_mean)/cc_std #标准化
  75. cc_zscore = cc_zscore.dropna(axis=0, how='any')
  76. cc_zscore_corr = cc_zscore.corr(method='spearman')
  77. result = []
  78. for i in range(len(cc_zscore_corr)):
  79. v = abs(np.array((sorted(cc_zscore_corr.iloc[i]))[2:-1])).mean() # 去掉1 和两个最小值后求均值
  80. result.append(v)
  81. return cc_zscore_corr, result
  82. # 输出偏离的情况,记录到数据库
  83. def instorage(sn, df_voltdiff_result, df_volt_result):
  84. df_all_result = pd.DataFrame(columns=['sn', 'time', 'cellnum', 'value', 'type'])
  85. value_list = []
  86. cellnum_list = []
  87. time_list = []
  88. type_list = []
  89. df_result = df_voltdiff_result.copy()
  90. time_list_1 = df_voltdiff_result['time']
  91. df_result = df_result[(df_result>3) | (df_result<-3)].dropna(axis=0, how='all').dropna(axis=1, how='all')
  92. for column in df_result.columns:
  93. df = df_result[[column]].dropna(axis=0, how='all')
  94. value_list.extend(df[column].tolist())
  95. cellnum_list.extend([column]*len(df))
  96. time_list.extend([time_list_1[x] for x in df.index])
  97. length_1 = len(value_list)
  98. df_result = df_volt_result.copy()
  99. time_list_2 = df_volt_result['time']
  100. df_result = df_result[(df_result>3) | (df_result<-3)].dropna(axis=0, how='all').dropna(axis=1, how='all')
  101. for column in df_result.columns:
  102. df = df_result[[column]].dropna(axis=0, how='all')
  103. value_list.extend(df[column].tolist())
  104. cellnum_list.extend([column]*len(df))
  105. time_list.extend([time_list_2[x] for x in df.index])
  106. length_2 = len(value_list) - length_1
  107. type_list.extend(['电压变化量离群'] * length_1)
  108. type_list.extend(['电压离群'] * length_2)
  109. df_all_result['sn'] = [sn] * len(value_list)
  110. df_all_result['cellnum'] = cellnum_list
  111. df_all_result['value'] = value_list
  112. df_all_result['time'] = time_list
  113. df_all_result['type'] = type_list
  114. return df_all_result
  115. # 报警.如果在某个窗口内,有超过ratio个的点,偏离度超过threshold, 则报警
  116. def alarm(dfin, volt_column, alarm_window=10, alarm_ratio=0.8, alarm_threshold=2.5):
  117. time_list = dfin['time'].tolist()
  118. df_result = dfin[volt_column].copy()
  119. alarm_result = pd.DataFrame(columns=['type', 'num', 'alarm_time'])
  120. df_result_1 = df_result.copy()
  121. df_result_1[df_result_1<alarm_threshold] = 0
  122. df_result_1[df_result_1>alarm_threshold] = 1
  123. df_result_1 = df_result_1.rolling(alarm_window).sum()
  124. for column in volt_column:
  125. if len(df_result_1[df_result_1[column]>alarm_window * alarm_ratio])>0:
  126. alarm_result = alarm_result.append({'type':'1', 'num':column, 'alarm_time':time_list[df_result_1[df_result_1[column]>alarm_window * alarm_ratio].index[0]]}, ignore_index=True)
  127. # time_list = time_list[window-1::step]
  128. df_result_2 = df_result.copy()
  129. df_result_2[df_result_2>-alarm_threshold] = 0
  130. df_result_2[df_result_2<-alarm_threshold] = 1
  131. df_result_2 = df_result_2.rolling(alarm_window).sum()
  132. for column in volt_column:
  133. if len(df_result_2[df_result_2[column]>alarm_window * alarm_ratio])>0:
  134. alarm_result = alarm_result.append({'type':'2', 'num':column, 'alarm_time':time_list[df_result_2[df_result_2[column]>alarm_window * alarm_ratio].index[0]]}, ignore_index=True)
  135. return alarm_result