datatable怎么根据两列分组_公司要IT转型,我该怎么办?用Python进行数据处理
“ 以后數據處理,都用pandas”
01 面臨問題
作為運維人員,每周要統計很多數據,特別是周四寫周報的時候,基本要花半天時間。既然已經學了Python,那就試試優化它。以統計不同廠家、不同設備類型告警量為例。
需要將多份類似表格中的 “廠家-設備類型” Sheet數據合并、處理、匯總,該sheet的數據格式如下:
期望按照廠家、設備類型匯總告警量,并進行分析。由于部分廠家、設備類型可能缺失導致無法對齊,無法自動相加。又是常態化重復工作,需要自動化解決方案。
02怎么辦
Python提供很多強大的數據分析相關的庫,如numpy、pandas等。下面就看看pandas如何幫助我們實現轉型吧。
pandas讀取excel
import pandas as pd #定義待讀取的文件名 filename1 = '全量告警_38AB1AE7.xlsx' filename2 = '全量告警_964C9DCF.xlsx' #使用pandas的函數讀取excel,當前目錄,直接寫文件名即可,可以有很多參數,這里指定所需sheet df1 = pd.read_excel(filename1,sheetname='廠家-設備類型') df2 = pd.read_excel(filename2,sheetname='廠家-設備類型')以上代碼可以讀取兩個excel文件。通過pandas.head() 可以顯示前幾行數據,快速查看DataFrame的格式,如列名,數據類型等,判斷是否正確載入數據。
pandas按照特定列合并處理
兩個df如何按照廠家和設備類型對告警量進行累加呢?就是按照“廠家”和“設備類型”兩列進行處理。最容易理解的辦法就是循環,通過遍歷所有廠家和設備類型組合,然后將每個df對應的值求和。
首先要知道兩個文件的最大廠家、設備類型集合,然后再遍歷。
#獲取兩個文件的最大廠家、設備類型集合 cjlx1 = [tuple(df1.loc[i][['廠家','設備類型']]) for i in df1.index] cjlx2 = [tuple(df2.loc[i][['廠家','設備類型']]) for i in df2.index] cjlx = set(cjlx1+cjlx2) #遍歷最大設備類型集合,求得合并告警量 rows = [] #輸出列表集合,可以轉換為DataFrame for i in cjlx: #遍歷最大(廠家、類型)集合cj = i[0] #獲取廠家名稱lx = i[1] #獲取設備類型if i in cjlx1: #如果該(廠家,類型)對在文件1中,取得對應告警量,否則告警量為0num1 = df1[(df1['廠家'] == cj) & (df1['設備類型']==lx)]['告警量'].iloc[0]else:num1 = 0if i in cjlx2:num2 = df2[(df2['廠家'] == cj) & (df2['設備類型']==lx)]['告警量'].iloc[0]else:num2 = 0 num = num1 + num2 #兩個告警量相加row = [cj,lx,num] #生成新的一行數據rows.append(row) #追加到輸出列表 data = pd.DataFrame(rows,columns = ['廠家','設備類型','告警量']) #轉換為DataFrame輸出data已經是匯總后的數據,可以用代碼檢查下。
In[112]: len(df1),len(df2),len(data) #In表示輸入,冒號后才是真實代碼 Out[112]: (71, 78, 80) In[113]:data.head() Out[113]: 廠家 設備類型 告警量 0 CISCO 交換機 2021 1 東信 HOST 56 2 東信 交換機 16 3 中興 HOST 182 4 愛立信 HSS_SLF 2可以發現原始兩個文件一個有71行數據,一個78行數據,合并后數據80行。
Pandas優化處理
Pandas是一個非常優秀的數據處理庫,實現上述功能肯定不用這么復雜。自帶的函數可以快速合并、規整兩個DataFrame。主要有append、merge和concat等操作。
append
可以在df后添加行或者另一個df。對合并后的df3進行分組groupby處理,按照告警量列進行求和(分組鍵會作為index,需要提取出來作為新的一列):
In[125]:df3 = df1.append(df2) In[125]:len(df1),len(df2),len(df3) #df3的行數是df1 和df2的和 Out[125]: (71, 78, 149)merge
通過一個或多個鍵(列名)將行連接起來。支持多種連接方式,左連接,右連接等,類似數據庫join操作。其中on表示用哪些鍵連接起來,how表示連接方式。
In[135]:df4 = pd.merge(df1,df2,on=['廠家','設備類型'],how = 'outer') In[136]:df1.shape,df2.shape,df4.shape, #可以發現df4是80*4,其中80行已經是最大集合,是我們想要的結果, Out[136]: ((71, 3), (78, 3), (80, 4)) In[137]:df4.head() Out[137]: 廠家 設備類型 告警量_x 告警量_y 0 CISCO HOST 16.0 1.0 1 CISCO 交換機 1484.0 537.0 2 CISCO 路由器 93.0 152.0 3 IBM HOST 702.0 745.0 4 JUNIPER 路由器 7.0 6.0其中告警量_x,告警量_y是原先兩個告警量,相同列名會自動增加_x和_y,以便區分。接下來只需將這兩列相加即可。
df4['告警量'] = df4['告警量_x'] + df4['告警量_y']這樣直接相加會有問題,存在nan值問題(某些廠家設備類型數據缺失)。
需要在相加之前進行處理。將nan值替換為0,再求和。
優化后代碼如下:
#使用pd.merge() 快速連接 data = pd.merge(df1,df2,on=['廠家','設備類型'],how = 'outer') #連接兩個df data = data.fillna(0) #用0替換nan值 data['告警量'] = data['告警量_x'] + data['告警量_y'] #兩個告警量相加,得到新的一列告警量 data = data[['廠家','設備類型','告警量']] #只選取我們想要的三列以上結果和循環遍歷結果一致。
Pandas文件保存
Pandas可以非常方便將文件保存為各種格式,如df.to_csv()、df.to_excel()。建議直接使用to_csv,簡單快速。
data.to_csv('out.csv',encoding= 'gbk',index = False) lsC:Userszhuf0Documentsrepositorypythondemo 的目錄2018/04/04 08:44 <DIR> . 2018/04/04 08:44 <DIR> .. 2018/04/04 08:44 521 out.csv可以發現當前目錄已經有out.csv。其中encoding設置了編碼方式、index可以設置是否保存索引。
代碼優化
上面已經實現了核心功能,下面將代碼優化一下,以便復用。
優化1 基本功能函數化
編寫一個函數,輸入兩個df,返回求和后df。
def get_df_sums(df1,df2):if df1.empty: #檢查其中一個df為空return df2elif df2.empty:return df1else:data = pd.merge(df1,df2,on=['廠家','設備類型'],how = 'outer') #連接兩個dfdata = data.fillna(0) #用0替換nan值data['告警量'] = data['告警量_x'] + data['告警量_y'] #兩個告警量相加,得到新的一列告警量data = data[['廠家','設備類型','告警量']] #只選取我們想要的三列return data優化2 自動讀取多個文件
一般情況下,待匯總的文件不止兩個,我們可以使用Python腳本自動讀取某個特定路徑下所有文件。
import os path = r"C:UserstestDocumentsrepositorypythondemo" out = pd.DataFrame() for filename in os.listdir(path):#遍歷指定路徑的所有文件名if '全量告警' in filename: #選擇指定文件待讀取filename = path+""+filename #獲取絕對路徑df1 = pd.read_excel(filename,sheetname='廠家-設備類型') #讀取該sheetout = get_df_sums(out,df1) #和之前的out累積求和,類似 sum=sum+i只需要將待匯總的文件放到指定目錄即可,輸出out.csv。
優化3 排序后保存
Pandas 有很強大的排序功能。sort_values如按照告警量排序:
In[164]out = out.sort_values(by = '告警量',ascending = False) #按照告警量降序排列 In[164]:out.head() Out[164]: 廠家 設備類型 告警量 7 愛立信 BSC 481307.0 65 中興 MME 163725.0 14 愛立信 MME 99553.0 13 愛立信 MGW 37488.0 16 愛立信 MSC_Server 24683.0留個問題
思考能否分組排序,按廠家分組,如愛立信,然后組內告警量降序排列。廠家的排序方式按照該廠家的最大告警量排序,而不是廠家的名稱。如愛立信后是中興。
最終代碼
最終優化后腳本為,保存為pandas_demo.py文件:
import pandas as pd import os #給定兩個df,返回求和后結果 def get_df_sums(df1,df2):if df1.empty: #檢查其中一個df為空return df2elif df2.empty:return df1else:data = pd.merge(df1,df2,on=['廠家','設備類型'],how = 'outer') #連接兩個dfdata = data.fillna(0) #用0替換nan值data['告警量'] = data['告警量_x'] + data['告警量_y'] #兩個告警量相加,得到新的一列告警量data = data[['廠家','設備類型','告警量']] #只選取我們想要的三列return data #給定路徑path,求和指定格式全部文件 def get_all_path(path):out = pd.DataFrame()for filename in os.listdir(path):#遍歷指定路徑的所有文件名if '全量告警' in filename: #選擇指定文件待讀取filename = path+""+filename #獲取絕對路徑df1 = pd.read_excel(filename,sheetname='廠家-設備類型') #讀取該sheetout = get_df_sums(out,df1) #和之前的out累積求和,類似 sum=sum+iout = out.sort_values(by = '告警量',ascending = False)return out#作為主程序運行 if __name__ =='__main__':path = r"C:UserstestDocumentsrepositorypythondemo"out = get_all_path(path)out.to_csv('out.csv',encoding= 'gbk',index = False) #保存腳本使用
只要我們將待處理的文件放到該目錄,然后命令行運行該腳本即可。
執行 python pandas_demo.py 沒有任何提示,說明成功。
至此,在公司IT轉型過程中,我用Python完成了第一個小項目,提升自我工作效率,省下的時間可以繼續學習了。
03 為什么
為什么要這么做?
職場學習就是要提升生產力,將日常重復性低價值工作交給機器。
Pandas是一個強大的數據分析第三方庫,Anaconda已經自動攜帶,無需安裝,只需import導入即可使用。一般用以下語法:
import pandas as pdPandas提供兩種常用的數據結構:Series和DataFrame。
其中Series可以看作一行或一列數據,DataFrame是一個二維表格數據,和excel表格類似,有行索引和列索引。
Pandas提供很多便捷的函數,用來創建、處理、保存DataFrame。
從office的Excel表格切換到Pandas非常容易理解。
在自動化、智能化演進過程中,公司要轉型,個人也要。
從身邊小事做起,代碼讓工作更美好。
04 其他選擇
有沒有更好的選擇?
除了merge,concat可以實現類似的連接,然后再進行處理。如有興趣可以思考。
腳本可以繼續優化
進一步優化將路徑作為參數提供,指定輸出目錄,增加一些提示性輸出,增加腳本穩健性。pandas海量數據處理優化
大數據處理是一個經典問題,如何優化效率已經是編碼之道。
暫時能力有限,不能涉及。很多牛人已經完成優化,還有很多類似的第三方庫,如datatable等。
作為初學者,選擇一個合適的,先入門。如果主要工作內容是大數據處理與分析,那么后面慢慢深入研究而得道。期待你的分享。
歡迎大家留言討論。
下篇我會繼續分享第二個小項目實踐,歡迎關注。
總結
以上是生活随笔為你收集整理的datatable怎么根据两列分组_公司要IT转型,我该怎么办?用Python进行数据处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 改变文件夹属性,技术|在Li
- 下一篇: websocket python爬虫_p