VoltStray.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. from re import X
  2. import pandas as pd
  3. import numpy as np
  4. from pandas.core.frame import DataFrame
  5. from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import BatParam
  6. import pandas as pd
  7. # 计算充电过程
  8. def preprocess(df):
  9. # 滤除前后电压存在一增一减的情况(采样异常)
  10. pass
  11. # 计算SOC变化率
  12. def cal_volt_change(dfin, volt_column):
  13. df = dfin.copy()
  14. df_volt_rolling = df[volt_column]
  15. df_volt_rolling_sum=df_volt_rolling.sum(1)-df_volt_rolling.max(1)
  16. df_volt_rolling_sum=df_volt_rolling_sum-df_volt_rolling.min(1)
  17. mean1 = df_volt_rolling_sum/(len(volt_column)-2)
  18. df_volt_rolling_norm = df_volt_rolling.sub(mean1, axis=0)#.div(std,axis=0)
  19. df_volt_rolling_norm = df_volt_rolling_norm.reset_index(drop=True)#和均值的距离
  20. return df_volt_rolling_norm
  21. # 计算电压离群
  22. def cal_volt_sigma(dfin, volt_column):
  23. df = dfin.copy()
  24. df_volt_rolling = df[volt_column]
  25. mean1=df_volt_rolling.mean(axis=1)
  26. std = df_volt_rolling.std(axis=1)
  27. std = std.replace(0,0.000001)
  28. df_volt_rolling = df_volt_rolling.sub(mean1, axis=0).div(std,axis=0)
  29. df_volt_rolling = df_volt_rolling.reset_index(drop=True)#分布
  30. return df_volt_rolling
  31. # # 计算电压变化量的偏离度
  32. # def cal_voltdiff_uniform(dfin, volt_column, window=10, step=5, window2=10, step2=5,threshold=3):
  33. # df = dfin.copy()
  34. # time_list = dfin['time'].tolist()
  35. # # 电压滤波
  36. # df_volt = df[volt_column]
  37. # df_volt_rolling = df_volt.rolling(window).mean()[window-1::step] # 滑动平均值
  38. # time_list = time_list[window-1::step]
  39. # # 计算电压变化量的绝对值(# 计算前后的差值的绝对值, 时间列-1)
  40. # df_volt_diff = abs(df_volt_rolling.diff()[1:])
  41. # df_volt_diff = df_volt_diff.reset_index(drop=True)
  42. # time_list = time_list[1:]
  43. # # 压差归一化(偏离度)
  44. # # mean = df_volt_diff.mean(axis=1)
  45. # # std = df_volt_diff.std(axis=1)
  46. # # df_voltdiff_norm = df_volt_diff.sub(mean, axis=0).div(std,axis=0)
  47. # df_voltdiff_norm = df_volt_diff.copy()
  48. # # 压差偏离度滑动平均滤波
  49. # df_voltdiff_rolling = df_voltdiff_norm.rolling(window2).mean()[window2-1::step2] # 滑动平均值
  50. # time_list = time_list[window2-1::step2]
  51. # df_voltdiff_rolling_sum=df_voltdiff_rolling.sum(1)-df_voltdiff_rolling.max(1)
  52. # df_voltdiff_rolling_sum=df_voltdiff_rolling_sum-df_voltdiff_rolling.min(1)
  53. # mean = df_voltdiff_rolling_sum/(len(volt_column)-2)
  54. # std = df_voltdiff_rolling.std(axis=1)
  55. # # mean = [np.array(sorted(x)[1:-1]).mean() for x in df_voltdiff_rolling.values]
  56. # # std = [np.array(sorted(x)[1:-1]).std() for x in df_voltdiff_rolling.values]
  57. # df_voltdiff_rolling_norm = df_voltdiff_rolling.sub(mean, axis=0)#.div(std,axis=0)
  58. # df_voltdiff_rolling_norm = df_voltdiff_rolling_norm.reset_index(drop=True)
  59. # return df_voltdiff_rolling_norm, time_list
  60. def main(sn,df_bms,df_soh,celltype,df_last):
  61. df_ram=pd.DataFrame(columns=['sn','time4','cellsoc'])
  62. param=BatParam.BatParam(celltype)
  63. df_bms['总电流[A]']=df_bms['总电流[A]']*param.PackCrntDec
  64. df_bms.rename(columns = {'总电流[A]':'PackCrnt'}, inplace=True)
  65. df_bms['time']=pd.to_datetime(df_bms['时间戳'], format='%Y-%m-%d %H:%M:%S')
  66. volt_column = ['单体电压'+str(i) for i in range(1,param.CellVoltNums+1)]
  67. columns=['time']+volt_column
  68. df_bms=df_bms[(df_bms['SOC[%]']>10)]
  69. # df_bms=df_bms[(df_bms['PackCrnt']<1)]
  70. # df_chrg=df_bms[(df_bms['PackCrnt']<-1)]
  71. #电压/SOC变化率计算
  72. if celltype<50:
  73. df_ram=pd.DataFrame(columns=['sn','time4','cellsoc'])
  74. df_ori = df_bms[columns]
  75. df = df_ori.drop_duplicates(subset=['time']) # 删除时间相同的数据
  76. df= df.set_index('time')
  77. df=df[(df[volt_column]>2000) & (df[volt_column]<4500)]
  78. df[volt_column]=pd.DataFrame(df[volt_column],dtype=np.float)
  79. df=df.resample('H').mean() #取一个小时的平均值
  80. df=df.dropna(how='any')
  81. time_list1=df.index.tolist()
  82. fun=lambda x: np.interp(x/1000, param.LookTab_OCV, param.LookTab_SOC)
  83. df_soc=df.applymap(fun)
  84. if (not df_soh.empty) and len(df_soc)>1:
  85. if (not df_last.empty) and (time_list1[0]-df_last.loc[0,'time4']).total_seconds()<12*3600:
  86. df_delt_soc1=df_soc-df_last.loc[0,'cellsoc']
  87. cellsoh=eval(df_soh.loc[0,'cellsoh'])
  88. df_delt_soc2=df_delt_soc1*np.array(cellsoh)/100
  89. df_delt_soc=df_delt_soc2-df_delt_soc1
  90. df_soc=df_soc+df_delt_soc
  91. else:
  92. df_delt_soc1=df_soc-df_soc.iloc[0]
  93. cellsoh=eval(df_soh.loc[0,'cellsoh'])
  94. df_delt_soc2=df_delt_soc1*np.array(cellsoh)/100
  95. df_delt_soc=df_delt_soc2-df_delt_soc1
  96. df_soc=df_soc+df_delt_soc
  97. df_ram.loc[0]=[sn,df_soc.index[-1],list(df_soc.iloc[-1])]
  98. else:
  99. df_ram=df_last
  100. VolChng = cal_volt_change(df_soc,volt_column)
  101. else:
  102. # df_bms=df_bms[(df_bms['PackCrnt']>-0.1) & (df_bms['PackCrnt']<0.1)]
  103. df_ori = df_bms[columns]
  104. df = df_ori.drop_duplicates(subset=['time']) # 删除时间相同的数据
  105. df= df.set_index('time')
  106. df=df[(df[volt_column]>3200) & (df[volt_column]<3400)]
  107. df[volt_column]=pd.DataFrame(df[volt_column],dtype=np.float)
  108. df=df.resample('H').mean() #取一个小时的平均值
  109. df=df.dropna(how='any')
  110. time_list1=df.index.tolist()
  111. VolChng = cal_volt_change(df,volt_column)
  112. VolSigma = cal_volt_sigma(df,volt_column)
  113. OutLineVol=DataFrame(columns=['time','sn','VolOl_Uni','VolChng_Uni'])
  114. #电压变化率和离群度计算
  115. if len(VolChng)>5 and len(VolSigma)>5:
  116. VolChng['time'] = time_list1
  117. VolChng= VolChng.set_index('time')
  118. VolChng_Uni_result=VolChng.values.tolist()#改
  119. VolSigma['time'] = time_list1
  120. VolSigma= VolSigma.set_index('time')
  121. VolOl_Uni_result=VolSigma.values.tolist()#改
  122. for i in range(0,len(VolChng)):
  123. if max(VolOl_Uni_result[i])>3 and min(VolOl_Uni_result[i])<-3:
  124. pass
  125. else:
  126. OutLineVol.loc[i,'VolOl_Uni']=str(list(np.around(VolOl_Uni_result[i],decimals=2)))
  127. OutLineVol.loc[i,'VolChng_Uni']=str(list(np.around(VolChng_Uni_result[i],decimals=2)))
  128. OutLineVol=OutLineVol[~OutLineVol['VolOl_Uni'].str.contains('nan')]
  129. OutLineVol=OutLineVol[~OutLineVol['VolChng_Uni'].str.contains('nan')]
  130. OutLineVol=OutLineVol.applymap((lambda x:''.join(x.split()) if type(x) is str else x))
  131. OutLineVol=OutLineVol.reset_index(drop=True)
  132. OutLineVol['time']= VolSigma.index
  133. OutLineVol['sn']=sn
  134. return(OutLineVol,df_ram)
  135. # this_alarm = {}
  136. # df_alarm = df_voltdiff_rolling_norm[abs(df_voltdiff_rolling_norm)>threshold].dropna(how='all')
  137. # for index in df_alarm.index:
  138. # df_temp = df_alarm.loc[index, :].dropna(how='all', axis=0)
  139. # 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()])]})
  140. # df_alarm1 = pd.DataFrame(this_alarm)
  141. # 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)
  142. # # 孤立森林算法
  143. # def iso_froest(df):
  144. # #1. 生成训练数据
  145. # rng = np.random.RandomState(42)
  146. # X = 0.3 * rng.randn(100, 2) #生成100 行,2 列
  147. # X_train = np.r_[X + 2, X - 2]
  148. # print(X_train)
  149. # # 产生一些异常数据
  150. # X_outliers = rng.uniform(low=-4, high=4, size=(20, 2))
  151. # iForest= IsolationForest(contamination=0.1)
  152. # iForest = iForest.fit(X_train)
  153. # #预测
  154. # pred = iForest.predict(X_outliers)
  155. # print(pred)
  156. # # [-1 1 -1 -1 -1 -1 -1 1 -
  157. # # 计算相关系数
  158. # def cal_coff(df):
  159. # cc_mean = np.mean(df, axis=0) #axis=0,表示按列求均值 ——— 即第一维
  160. # cc_std = np.std(df, axis=0)
  161. # cc_zscore = (df-cc_mean)/cc_std #标准化
  162. # cc_zscore = cc_zscore.dropna(axis=0, how='any')
  163. # cc_zscore_corr = cc_zscore.corr(method='spearman')
  164. # result = []
  165. # for i in range(len(cc_zscore_corr)):
  166. # v = abs(np.array((sorted(cc_zscore_corr.iloc[i]))[2:-1])).mean() # 去掉1 和两个最小值后求均值
  167. # result.append(v)
  168. # return cc_zscore_corr, result
  169. # def instorage(sn, df_voltdiff_result, df_volt_result):
  170. # df_all_result = pd.DataFrame(columns=['sn', 'time', 'cellnum', 'value', 'type'])
  171. # value_list = []
  172. # cellnum_list = []
  173. # time_list = []
  174. # type_list = []
  175. # df_result = df_voltdiff_result.copy().drop(columns='time')
  176. # time_list_1 = df_voltdiff_result['time']
  177. # df_result = df_result[(df_result>3) | (df_result<-3)].dropna(axis=0, how='all').dropna(axis=1, how='all')
  178. # for column in df_result.columns:
  179. # df = df_result[[column]].dropna(axis=0, how='all')
  180. # value_list.extend(df[column].tolist())
  181. # cellnum_list.extend([column]*len(df))
  182. # time_list.extend([time_list_1[x] for x in df.index])
  183. # length_1 = len(value_list)
  184. # df_result = df_volt_result.copy().drop(columns='time')
  185. # time_list_2 = df_volt_result['time']
  186. # df_result = df_result[(df_result>3) | (df_result<-3)].dropna(axis=0, how='all').dropna(axis=1, how='all')
  187. # for column in df_result.columns:
  188. # df = df_result[[column]].dropna(axis=0, how='all')
  189. # value_list.extend(df[column].tolist())
  190. # cellnum_list.extend([column]*len(df))
  191. # time_list.extend([time_list_2[x] for x in df.index])
  192. # length_2 = len(value_list) - length_1
  193. # type_list.extend(['电压变化量离群'] * length_1)
  194. # type_list.extend(['电压离群'] * length_2)
  195. # df_all_result['sn'] = [sn] * len(value_list)
  196. # df_all_result['cellnum'] = cellnum_list
  197. # df_all_result['value'] = value_list
  198. # df_all_result['time'] = time_list
  199. # df_all_result['type'] = type_list
  200. # return df_all_result
  201. # # 报警.如果在某个窗口内,有超过ratio个的点,偏离度超过threshold, 则报警
  202. # def alarm(dfin, volt_column, alarm_window=10, alarm_ratio=0.8, alarm_threshold=2.5):
  203. # time_list = dfin['time'].tolist()
  204. # df_result = dfin[volt_column].copy()
  205. # alarm_result = pd.DataFrame(columns=['type', 'num', 'alarm_time'])
  206. # df_result_1 = df_result.copy()
  207. # df_result_1[df_result_1<alarm_threshold] = 0
  208. # df_result_1[df_result_1>alarm_threshold] = 1
  209. # df_result_1 = df_result_1.rolling(alarm_window).sum()
  210. # for column in volt_column:
  211. # if len(df_result_1[df_result_1[column]>alarm_window * alarm_ratio])>0:
  212. # 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)
  213. # # time_list = time_list[window-1::step]
  214. # df_result_2 = df_result.copy()
  215. # df_result_2[df_result_2>-alarm_threshold] = 0
  216. # df_result_2[df_result_2<-alarm_threshold] = 1
  217. # df_result_2 = df_result_2.rolling(alarm_window).sum()
  218. # for column in volt_column:
  219. # if len(df_result_2[df_result_2[column]>alarm_window * alarm_ratio])>0:
  220. # 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)
  221. # return alarm_result