2017-04-26 93 views
1

我遇到以下需要幫助的問題。 我有一個csv文件中的310條記錄,其中包含一些關於錯誤的信息。 在另一個csv文件中,我有80萬條包含有關行李統計的記錄(可能導致錯誤的事件)。通過熊貓數據幀進行高效循環

與下面的腳本,我通過漏洞試圖

  1. 循環,並選擇一個。
  2. 循環通過統計記錄和檢查一些條件
  3. 如果有匹配,從錯誤記錄統計 記錄添加一列。
  4. 另存新文件

我的問題是,如果我能在使用numpy的或任何其他更有效的方式archieve這一點。 目前的方法是採取永遠因爲統計

任何幫助或提示在正確的方向的大小的運行將不勝感激。 感謝名單中adavance

dataset = pd.read_csv('310_records.csv') 
dataset1 = pd.read_csv('800K_records.csv') 
cols_error = dataset.iloc[:, [0, 1, 2, 3, 4, 5, 6]] 
cols_stats = dataset1.iloc[:, [1, 2, 3, 4, 5, 6, 7, 8, 9]] 
cols_stats['Fault'] = '' 
cols_stats['Created'] = '' 

for i, error in cols_error.iterrows():  
    fault_created = error [0] 
    fault_ucs = error [1] 
    fault_dn = error [2] 
    fault_epoch_end = error [3] 
    fault_epoch_begin = error [4] 
    fault_code = error [6]  

    for index, stats in cols_stats.iterrows(): 
     stats_epoch = stats[0] 
     stats_ucs = stats[5]   
     stats_dn = stats[7] 
     print("error:", i, " Stats:", index)   

     if(stats_epoch >= fault_epoch_begin and stats_epoch <= fault_epoch_end): 
      if(stats_dn == fault_dn): 
       if(stats_ucs == fault_ucs): 
        cols_stats.iloc[index, 9] = fault_code 
        cols_stats.iloc[index, 10] = fault_created 

     else: 
      cols_stats.iloc[index, 9] = 0 
      cols_stats.iloc[index, 10] = fault_created 

cols_stats.to_csv('datasets/dim_stats_error.csv', sep=',', encoding='utf-8') 
+0

可能會被很多不說'print'聲明更快。 –

+0

@StefanPochmann注意到..我會擺脫那條線。 Thanx – Makten

+0

您可以在800k_records中搜索並隔離第三個文件中的所有錯誤(保留位置跟蹤)。並在第三個文件中進行匹配?此外,並行執行多個搜索將有助於 – pwnsauce

回答

1

首先:你確定你的代碼沒有你想要它做什麼?正如我所看到的那樣,您一直在循​​環查看統計信息,因此如果您發現了與bug#1匹配的錯誤,您可以稍後用錯誤#310覆蓋統計數據的相應附錄。目前還不清楚你應該如何處理沒有匹配錯誤事件的統計事件,但目前你在某些情況下爲這些數據點存儲了fault_created列。更不用說每次檢查每個錯誤的每個事件所做的額外工作。

緩慢的原因是你注意到利用熊貓的力量。在numpy和pandas中,性能都來自內存管理,其餘部分來自矢量化。通過將大部分工作從本地Python循環推送到矢量化函數(運行編譯代碼),您開始看到巨大的速度提升。

我不確定是否有向量化你的工作所有先進的方式,但因爲你是在看310 VS 800K的項目,似乎完全合理的保持環在你的錯誤和矢量化內環。最關鍵的是合理的索引,使用它你可以一次解決所有800K項目:

for i, error in cols_error.iterrows(): 
    created, ucs, dn, epoch_end, epoch_begin, _, code = error 

    inds = ((epoch_begin <= cols_stats['epoch']) & 
      (cols_stats['epoch'] <= epoch_end) & 
      (cols_stats['dn'] == dn) & 
      (cols_stats['ucs'] == ucs)) 
    cols_stats['Fault'][inds] = code 
    cols_stats['Created'][inds] = created 

cols_stats.to_csv('datasets/dim_stats_error.csv', sep=',', encoding='utf-8') 

注意上面不會將無與倫比列的東西不平凡的,因爲我不認爲你有一個合理的在你的問題中的例子。無論你想設置什麼樣的默認值,都應該獨立於bug列表,所以你應該在整個匹配考驗之前設置這些值。

請注意,我爲您的代碼做了一些整容。您可以使用拆包分配來設置error中的所有這些值,並且刪除這些變量的前綴可以使其更清晰。由於我們沒有爲統計數據框定義單獨的變量,因此我們可以處理前綴。

正如您所看到的,您可以根據向量化邏輯索引操作來定義查找給定錯誤的所有匹配統計項的條件。生成的大熊貓Series調用inds對於統計數據框的每一行都有一個布爾值。這可以用於分配給名爲'Fault''Created'的列的子集。請注意,您可以(也可能應該)按名稱對列進行索引,至少我覺得這個更清晰和方便。

由於每個錯誤您codecreated是標量(可能是字符串),該矢量分配cols_stats['Fault'][inds] = codecols_stats['Created'][inds] = createdcols_stats每個索引項設置爲這些標量。

我相信結果應該和以前一樣,但要快得多,代價是增加內存使用。

可以在初始化時進一步簡化,但如果沒有MCVE,則很難說具體細節。至少,你可以用切片的符號:

cols_error = dataset.iloc[:, :7] 
cols_stats = dataset1.iloc[:, 1:10] 

但賠率是你只是忽略了幾列,在這種情況下,它可能更清楚drop那些代替。例如,如果在dataset你有一個名爲「垃圾」,你忽略了一個第七列,你可以設置

cols_error = dataset.drop('junk', axis=1) 
+0

非常感謝您的詳細解釋。具有很大的意義。我的名聲不夠高,無法接受這個答案,但它確實符合我的意願。豎起大拇指;) – Makten

+0

@Makten我很高興它的作品。但是你不需要聲望來接受答案:這是任何一個adker都能做的事情:)你只需要點擊答案左邊的刻度線。 –

+0

啊..不知道。感謝名單 – Makten