侯波濤
(中國西南電子技術(shù)研究所,四川 成都 610036)
隨著數(shù)據(jù)科學(xué)的發(fā)展,數(shù)據(jù)分析呈現(xiàn)流行之勢,幾乎滲透到自然科學(xué)、社會科學(xué)的方方面面。數(shù)據(jù)分析致力于從海量數(shù)據(jù)中挖掘有效信息,通過可視化等手段展示數(shù)據(jù)中隱含的規(guī)律。Python 是一種面向?qū)ο?、解釋型、動態(tài)類型程序設(shè)計語言[1-3],隨著Numpy、Scipy、Pandas、Matplotlib 等眾多庫的開發(fā)及優(yōu)化,Python 在科學(xué)計算領(lǐng)域占據(jù)著越來越重要的地位,包括科學(xué)計算、數(shù)學(xué)建模、數(shù)據(jù)分析等[4-6]。
Python 的Pandas 庫提供了便捷處理結(jié)構(gòu)化數(shù)據(jù)的大量數(shù)據(jù)結(jié)構(gòu)和函數(shù),兼具Numpy 高性能數(shù)組計算功能及電子表格和關(guān)系型數(shù)據(jù)庫(如SQL)靈活的數(shù)據(jù)處理功能[7-8],使得數(shù)據(jù)對齊、合并、缺失值處理、篩選、分組及聚合運(yùn)算非常便捷。pyecharts 是百度開源echarts 與python 結(jié)合強(qiáng)大的數(shù)據(jù)可視化工具,可提供直觀、生動、可交互、高度個性化定制的數(shù)據(jù)可視化圖表。本文利用pandas及pyecharts 對定向通信系統(tǒng)的組網(wǎng)性能、Qos、話音時序進(jìn)行了數(shù)據(jù)分析及可視化。
數(shù)據(jù)分析流程如圖1 所示,對存儲的二進(jìn)制記錄數(shù)據(jù)進(jìn)行十六進(jìn)制ASCII 碼轉(zhuǎn)換,將轉(zhuǎn)換后的數(shù)據(jù)進(jìn)行解析,再對解析后的數(shù)據(jù)進(jìn)行預(yù)處理,數(shù)據(jù)預(yù)處理主要包括數(shù)據(jù)清洗及預(yù)分析,缺失值、重復(fù)值、不一致數(shù)據(jù)處理、數(shù)據(jù)類型轉(zhuǎn)換等,通常占數(shù)據(jù)分析工作量的70%以上。對單節(jié)點(diǎn)文件BIT 結(jié)果進(jìn)行統(tǒng)計及可視化,對多節(jié)點(diǎn)文件兩兩之間進(jìn)行數(shù)據(jù)合并、分組、篩選、提取及可視化,利用篩選的數(shù)據(jù)及可視化圖形文件對網(wǎng)絡(luò)、Qos、話音進(jìn)行分析,對有無故障做出判斷并進(jìn)一步分析原因,最后撰寫數(shù)據(jù)分析報告。
圖1 數(shù)據(jù)分析流程
Pandas 的join 方法支持以索引或指定列連接兩個Dataframe。典型數(shù)據(jù)對齊、合并及缺失值處理如表1 所示,首先選擇一個基準(zhǔn)時間,一般選取周期類消息(如導(dǎo)航數(shù)據(jù))時標(biāo)或者自定義一個時間序列作為基準(zhǔn)時間序列,根據(jù)時間序列合并多條數(shù)據(jù)項,合并后先進(jìn)行列數(shù)據(jù)項縱向缺失值填充再進(jìn)行行數(shù)據(jù)項的橫向缺失值刪除處理,結(jié)合序號列可保證合并后的數(shù)據(jù)以基準(zhǔn)時間序列為周期,最后利用groupby 等函數(shù)進(jìn)行分組、聚合、篩選等處理,提取出關(guān)注信息。
表1 數(shù)據(jù)對齊、合并及缺失值處理
timeticks=pd.date_range(start=time_start,end=time_end,freq=’20L’) # 時間基準(zhǔn)20ms
df=pd.DataFrame({‘SN’:np.arange(len(timeticks))},index=timeticks) # 創(chuàng)建基準(zhǔn)時間序列
df=df.join([Data1,Data2,…,State1,State2,…],how=’outer’,on=’ts’)# 合并數(shù)據(jù)
df[‘Data1’].fillna(method=’pad’,inplace=True) # 按列缺失值填充
…
df.dropna(inplace=True) # 刪除空值行
數(shù)據(jù)可視化采用pyecharts 的散點(diǎn)圖Scatter 和折線圖Line,通過坐標(biāo)軸指示器配置項AxisPointerOpts和區(qū)域選擇組件配置項BrushOpts 可實現(xiàn)多圖聯(lián)動及區(qū)域選擇聯(lián)動。通過zip 將多維數(shù)據(jù)進(jìn)行打包,實現(xiàn)多維數(shù)據(jù)可視化。通過視覺映射組件VisualMapOpts 可將關(guān)注數(shù)據(jù)映射到視覺元素,通過提示框TooltipOpts 實現(xiàn)與鼠標(biāo)良好的交互性,實時顯示多維數(shù)據(jù),通過區(qū)域縮放配置項DataZoomOpts可實現(xiàn)區(qū)域縮放,展示出所關(guān)注的細(xì)節(jié)數(shù)據(jù)信息,生成獨(dú)立的html 圖表文件既可概覽整體,又可關(guān)注細(xì)節(jié),可獨(dú)立進(jìn)行交互式數(shù)據(jù)分析。
Python 自帶的binascii 模塊可將記錄數(shù)據(jù)由二進(jìn)制轉(zhuǎn)換為十六進(jìn)制ascii 碼,轉(zhuǎn)為字符串后使用split 函數(shù)根據(jù)幀頭標(biāo)識將字符串分割為數(shù)據(jù)幀列表,遍歷列表并用bytes().fromhex()將數(shù)據(jù)幀轉(zhuǎn)換為十進(jìn)制字節(jié)序列,最后根據(jù)接口控制文件解析數(shù)據(jù)幀內(nèi)容,對于超大文件需分塊讀取及處理以避免對內(nèi)存的過度消耗。
f=open(‘Record.bin’,’rb’) # 打開記錄文件
while True:
Data_b=f.read()
if not Data_b:
break
Data_s=str(binascii.hexlify(Data_b))[2:-1]#二進(jìn)制轉(zhuǎn)十六進(jìn)制
Frame=Data_s.split(‘XXXX’) # 根據(jù)幀頭XXXX 分割數(shù)據(jù)幀
for frame in Frame: #解析數(shù)據(jù)幀
frame_byte=bytes().fromhex(frame)#轉(zhuǎn)十進(jìn)制字節(jié)序列
數(shù)據(jù)分析時需綜合分析多條數(shù)據(jù)信息,每條數(shù)據(jù)有自身時間標(biāo)簽,對于通信節(jié)點(diǎn)A 和B,以A 的慣導(dǎo)數(shù)據(jù)為時間基準(zhǔn),利用Reindex 將B 的慣導(dǎo)數(shù)據(jù)進(jìn)行重新索引并進(jìn)行向上填充,再利用join 函數(shù)合并雙方慣導(dǎo)數(shù)據(jù),合并后計算雙節(jié)點(diǎn)距離。
Ins_AB=Ins_B.reindex(Ins_A.index,method=’pad’)#利用reindex 重新索引,向前填充
Ins=Ins_A.join(Ins_AB,how=’left’,lsuffix=’A’,rsuffix=’B’) #數(shù)據(jù)合并
Ins[‘Dis’]=Distance(df[‘Lat%s’%A],df[‘Lo n%s’%A],df[‘Alt%s’%A],df[‘Lat%s’%B],df[‘Lon%s’%B],df[‘Alt%s’%B]) #矢量計算距離
對于實時性要求較高的波束數(shù)據(jù)及網(wǎng)絡(luò)數(shù)據(jù),可將時元、時幀、時隙設(shè)置為層次化索引進(jìn)行精確對齊及合并。
Beam.set_index([‘Epoch’,’Frame’,’Slot’],inplace=True)#設(shè)置波束層次化索引
Net.set_index([‘Epoch’,’Frame’,’Slot’],in place=True) #設(shè)置網(wǎng)絡(luò)層次化索引
Beam_Net=Beam.join([Net],how=’outer’) #合并波束與網(wǎng)絡(luò)
Beam_Net.fillna(method=’pad’,inplace=True)#向前填充
最后根據(jù)時間序列將雙節(jié)點(diǎn)的慣導(dǎo)數(shù)據(jù)、波束及網(wǎng)絡(luò)數(shù)據(jù)、系統(tǒng)使用狀態(tài)數(shù)據(jù)進(jìn)行合并及缺失值處理,合并后數(shù)據(jù)如表2 所示。
表2 雙節(jié)點(diǎn)合并后數(shù)據(jù)
對于Qos 分析需根據(jù)用戶數(shù)據(jù)的消息序列號進(jìn)行對齊及合并,合并后進(jìn)行端到端時延計算,如表3 所示。
Pck=Pck_Send.join(Pck_Rcv,how=’outer’,on=’SN’,lsuffix=’T’,rsuffix=’R’,)# 以 序 列號合并
Pck[‘Delta’]=Pck[‘Ts_R’]-Pck[‘Ts_T’]#計算端到端時延
表3 用戶數(shù)據(jù)合并及處理
Pandas 憑借高度優(yōu)化的函數(shù)對結(jié)構(gòu)化數(shù)據(jù)進(jìn)行遍歷、分組及篩選非常便捷高效。為了分析網(wǎng)絡(luò)整體情況,需對表2 提取網(wǎng)絡(luò)由連接到斷開時刻及斷開到連接時刻第一次的數(shù)據(jù)并計算斷網(wǎng)持續(xù)時間,為了靈活處理需按行遍歷整個數(shù)據(jù)框,通過dataframe 的itertuples 函數(shù)可高效完成操作,實測遍歷100 萬行數(shù)據(jù)框并做簡單處理僅耗時13 秒,通過提取的數(shù)據(jù)可直觀看出網(wǎng)絡(luò)斷開及恢復(fù)時刻雙節(jié)點(diǎn)的距離、高度、姿態(tài)、天線、波束、SNR、系統(tǒng)使用狀態(tài)等信息。
for row in Data.itertuples():
epoch=getattr(row,‘Epoch’)
frame=getattr(row,‘Frame’)
slot=getattr(row,‘Slot’)
…
為了分析由于模擬信道性能下降而造成的網(wǎng)絡(luò)斷續(xù),以此作為硬件性能下降但BIT 無法給出故障判斷的輔助手段,可通過計算表2 多個天線兩兩配對時的通信成功概率(可通率),根據(jù)多個天線間的可通率計算結(jié)果快速定位故障天線或信道。用groupby 函數(shù)對表2 根據(jù)節(jié)點(diǎn)A 和B 的天線索引進(jìn)行分組篩選,根據(jù)篩選后的網(wǎng)絡(luò)狀態(tài)進(jìn)行統(tǒng)計并計算可通率,計算結(jié)果如表4,可直觀的看出節(jié)點(diǎn)A的天線1 有問題,代碼非常簡潔。
for (Ant_A,Ant_B),group in df.groupby([‘Ant_A’,‘Ant_B’]):
link_on=group[group[‘Net’]==1].shape[0]
link_off=group[group[‘Net’]]==0].shape[0]
off_time=link_off * 0.02 #斷開時間統(tǒng)計
on_rate=‘{:.3%}’.format(link_on/ (group.shape[0]))#計算可通率
表3 中計算丟包率只需統(tǒng)計合并后收端數(shù)據(jù)為空值的次數(shù),通過isnull 函數(shù)進(jìn)行篩選。
Pck_lost=Pck[Pck.Ts_R].isnull()]# 接收丟包數(shù)
LostRate=Pck_lost.shape[0]/ Pck.shape[0]# 計算丟包率
表4 可通率計算
對于表3 用戶消息需計算數(shù)據(jù)吞吐量,用groupby 分組聚合的辦法非常高效,根據(jù)整數(shù)秒數(shù)據(jù)進(jìn)行分組并計算每組中發(fā)送數(shù)據(jù)長度總和,代碼如下。
df[‘Epoch’]=[int(x.value/ 1000000000) for x in Pck[‘Ts_R’]]#時間轉(zhuǎn)為整數(shù)秒
grouped=df[‘LEN_T’].groupby(df[‘Epoch’])#根據(jù)整數(shù)秒進(jìn)行分組
Throughout=grouped.sum()*8 #轉(zhuǎn)換為bps,計算吞吐量
(1)多軸聯(lián)動數(shù)據(jù)可視化
對表2 中的網(wǎng)絡(luò)、距離、SNR、信道數(shù)據(jù)進(jìn)行同步顯示,滑動鼠標(biāo)可實現(xiàn)多圖聯(lián)動及區(qū)域放大,如圖2 所示。
(2)多維數(shù)據(jù)可視化及顏色映射
對表2 中網(wǎng)絡(luò)和距離數(shù)據(jù)作多維散點(diǎn)圖如圖3所示,以網(wǎng)絡(luò)狀態(tài)為顏色映射,過濾網(wǎng)絡(luò)斷開時刻后如圖4 所示,對通信雙方的距離、高度、天線、波束、SNR 信息進(jìn)行多維顯示。
圖2 多軸聯(lián)動數(shù)據(jù)可視化
圖3 距離與網(wǎng)絡(luò)關(guān)系
圖4 網(wǎng)絡(luò)斷開時刻信息
對表2 慣導(dǎo)航跡和SNR 數(shù)據(jù)作多維散點(diǎn)圖,用SNR 數(shù)據(jù)進(jìn)行顏色映射,如圖5 所示,可直觀看出區(qū)域分布,拖動SNR 范圍可查看對應(yīng)區(qū)域,滑動鼠標(biāo)動態(tài)放大可查看每個點(diǎn)的多維數(shù)據(jù)信息。
圖5 軌跡與SNR 多維數(shù)據(jù)可視化
(3)時序分析
根據(jù)時間標(biāo)簽將通信雙方的話音PTT 數(shù)據(jù)、收發(fā)話狀態(tài)數(shù)據(jù)進(jìn)行合并及缺失值處理,將數(shù)據(jù)項無效時刻替換為None(空值),進(jìn)行可視化如圖6所示,滑動放大可直觀看出收發(fā)雙方的時序關(guān)系,對發(fā)話異常、PTT 按壓時間較短、話音搶發(fā)等情況進(jìn)行直觀分析。
圖6 話音時序
(1)盡量使用內(nèi)置函數(shù)
Python 標(biāo)準(zhǔn)庫中有很多內(nèi)置函數(shù)是使用C 語言編寫的,運(yùn)行效率很高,所以在功能實現(xiàn)時優(yōu)先使用內(nèi)置函數(shù)可提高程序運(yùn)行效率。
(2)矢量計算
對數(shù)據(jù)集進(jìn)行并行計算等矢量運(yùn)算可顯著提高運(yùn)算效率。在數(shù)據(jù)量較大情況下避免使用for…in 循環(huán)迭代,盡量采用apply、pandas series 矢量化及numpy arrays 矢量化,使用values 方法將鏈表Pandas series 轉(zhuǎn)換為Numpy arrays 再進(jìn)行矢量運(yùn)算將會顯著提高運(yùn)算速度。
(3)多進(jìn)程與多線程
充分利用計算機(jī)的多核CPU 資源進(jìn)行并行處理,python 提供了非常好用的多進(jìn)程包multiprocessing,可輕松完成從單進(jìn)程到并發(fā)進(jìn)程的轉(zhuǎn)換,對數(shù)據(jù)密集型場景可極大提升處理效率。在GUI 設(shè)計時,為了防止執(zhí)行較耗時任務(wù)時造成的界面無響應(yīng),應(yīng)利用Thread 函數(shù)將多個任務(wù)加入多線程處理。
(4)避免內(nèi)存過度消耗
(a)讀取結(jié)構(gòu)化數(shù)據(jù)時指定數(shù)據(jù)類型,對大型數(shù)據(jù)框要進(jìn)行分塊讀??;
(b)數(shù)據(jù)合并后進(jìn)行缺失值處理后進(jìn)行強(qiáng)制類型轉(zhuǎn)換,表5 為數(shù)據(jù)類型轉(zhuǎn)換前后內(nèi)存占用對比;
(c)對無用數(shù)據(jù)及時進(jìn)行刪除處理釋放內(nèi)存。
表5 數(shù)據(jù)類型轉(zhuǎn)換前后內(nèi)存消耗對比
使用python 及matlab 語言實現(xiàn)本通信系統(tǒng)數(shù)據(jù)分析對比如表6 所示,可看出python 語言在代碼簡潔性、字節(jié)序列化、數(shù)據(jù)對齊、時間序列具有明顯優(yōu)勢。
表6 python 與matlab 性能對比
隨著大數(shù)據(jù)時代的日益發(fā)展,數(shù)據(jù)的獲取及分析已成為熱點(diǎn),python 語言成為目前數(shù)據(jù)分析領(lǐng)域最熱門的語言之一,可高效的實現(xiàn)數(shù)據(jù)分析,特別適合需求頻繁變化的敏捷開發(fā)場景。隨著越來越多高效庫的開發(fā)及活躍的社區(qū),python 的應(yīng)用會越來越廣泛[9]。本文利用python 實現(xiàn)了較大容量數(shù)據(jù)的解析、預(yù)處理、可視化等工作,并通過與matlab 語言的對比展示出了python 在數(shù)據(jù)分析領(lǐng)域的優(yōu)勢,對通信系統(tǒng)數(shù)據(jù)分析提供了一條便捷途徑。