8

我有一個處理DataFrame的函數,很大程度上是爲了將數據處理成存儲桶,並使用pd.get_dummies(df[col])在特定列中創建了要素的二進制矩陣。爲什麼數據幀的連接速度會呈指數級下降?

chunks = (len(df)/10000) + 1 
df_list = np.array_split(df, chunks) 

pd.get_dummies(df)會自動創建:

爲了避免處理所有使用該功能一次(這超出內存,並導致IPython的崩潰),我的數據,我已經用壞了的大數據幀成塊新列基於df[col]的內容,這些可能會在df_list中的每個df有所不同。

處理後,我串接DataFrames回到一起使用:

for i, df_chunk in enumerate(df_list): 
    print "chunk", i 
    [x, y] = preprocess_data(df_chunk) 
    super_x = pd.concat([super_x, x], axis=0) 
    super_y = pd.concat([super_y, y], axis=0) 
    print datetime.datetime.utcnow() 

第一小盤的處理時間是完全可以接受的,但是,它的增長每塊!這與preprocess_data(df_chunk)沒有關係,因爲沒有理由增加。由於致電pd.concat(),這是否會增加時間?

請參閱下面登錄:

chunks 6 
chunk 0 
2016-04-08 00:22:17.728849 
chunk 1 
2016-04-08 00:22:42.387693 
chunk 2 
2016-04-08 00:23:43.124381 
chunk 3 
2016-04-08 00:25:30.249369 
chunk 4 
2016-04-08 00:28:11.922305 
chunk 5 
2016-04-08 00:32:00.357365 

有一種解決方法,以加快這?我有2900塊處理,所以任何幫助表示讚賞!

在Python中打開任何其他建議!

回答

8

,一定不要調用DataFrame.appendpd.concat一個for循環中。它導致二次複製。

pd.concat返回一個新的DataFrame。空間必須分配給新的數據幀 ,舊數據幀中的數據必須複製到新的數據幀中。考慮複製由該行的for-loop內(假設每個x具有尺寸1)所需要的量:

super_x = pd.concat([super_x, x], axis=0) 

| iteration | size of old super_x | size of x | copying required | 
|   0 |     0 |   1 |    1 | 
|   1 |     1 |   1 |    2 | 
|   2 |     2 |   1 |    3 | 
|  ... |      |   |     | 
|  N-1 |     N-1 |   1 |    N | 

1 + 2 + 3 + ... + N = N(N-1)/2。所以有O(N**2)副本需要 完成循環。

現在考慮

super_x = [] 
for i, df_chunk in enumerate(df_list): 
    [x, y] = preprocess_data(df_chunk) 
    super_x.append(x) 
super_x = pd.concat(super_x, axis=0) 

追加到一個列表是一個O(1)操作,並不需要複製。現在, 循環完成後,將有一個呼叫到pd.concat。這調用 pd.concat要求進行N份,因爲super_x包含N DataFrames尺寸1.所以構建這樣的時候,super_x需要O(N) 副本。

+0

嗨@unutbu,感謝您的詳細解釋,這真的詳細解釋了理論! – jfive

+0

用這種方法(43717,3261)連接2900個這種形狀的塊是否可行?處理步驟現在只需要10秒。 – jfive

4

每次連接時,都會返回一份數據副本。

您想保留塊的列表,然後將所有內容拼接爲最後一步。

df_x = [] 
df_y = [] 
for i, df_chunk in enumerate(df_list): 
    print "chunk", i 
    [x, y] = preprocess_data(df_chunk) 
    df_x.append(x) 
    df_y.append(y) 

super_x = pd.concat(df_x, axis=0) 
del df_x # Free-up memory. 
super_y = pd.concat(df_y, axis=0) 
del df_y # Free-up memory. 
+0

非常感謝,解決了這個問題! – jfive

相關問題