2016-11-12 48 views
3

我發現,當您將大量數據集與大量列在同一列合併時,我發現與熊貓庫直接合並鏈是非常低效的。在熊貓中高效的鏈合併

問題的根源是一樣的,當我們加入了很多的STR的愚蠢方式: 加入=減少(拉姆達A + B,爲str_list) 相反的: 加入=「」。加入(爲str_list)

做連鎖合併,我們在一次或爲了

有一些有效的方法(通過在數字複製的數據集多次(在我的情況差不多100倍),而不是從幾個數據集,只是填充柱=與線性複雜度的集合)通過同一列鏈合併大量的數據集?

回答

3

如果您有dataframes dfs的列表:

dfs = [df1, df2, df3, ... , dfn] 

您可以用熊貓的concat功能,據我可以告訴比鏈接合併快加入他們的行列。 concat只能根據索引(不是列)加入數據幀,但只需稍加預處理即可模擬merge操作。

首先用您要合併的列替換dfs中每個數據框的索引。比方說,你想在"A"列合併:

dfs = [df.set_index("A", drop=True) for df in dfs] 

注意,這覆蓋以前的指標(合併會這樣呢),所以你可能要保存在某個地方,這些指標(如果你要需要他們後來出於某種原因)。

現在我們可以使用CONCAT這將在實質上指數合併(這是實際上你列 !!)

merged = pd.concat(dfs, axis=1, keys=range(len(dfs)), join='outer', copy=False) 

join=參數可以是'inner''outer'(默認)。 copy=參數使concat不會產生不必要的數據幀副本。

然後,您可以離開"A"作爲索引,或者你可以通過執行,使其恢復到列:

merged.reset_index(drop=False, inplace=True) 

keys=參數是可選的鍵值分配給每個數據幀(在這種情況下,我給它一個整數範圍,但你可以給他們其他標籤,如果你想)。這使您可以訪問原始數據框中的列。所以,如果你想獲得對應於dfs 20數據框列,您可以撥打:

merged[20] 

沒有keys=自變量,它可能會比較混亂,其行是從dataframes,特別是如果他們有相同的列名。

我還不能完全肯定,如果concat運行線性時間,但它絕對不是鏈接merge快:採用隨機產生的dataframes名單IPython中的%timeit

(10,100和1000 dataframes名單) :

def merge_with_concat(dfs, col):            
    dfs = [df.set_index(col, drop=True) for df in dfs] 
    merged = pd.concat(dfs, axis=1, keys=range(len(dfs)), join='outer', copy=False) 
    return merged 

dfs10 = [pd.util.testing.makeDataFrame() for i in range(10)] 
dfs100 = [pd.util.testing.makeDataFrame() for i in range(100)] 
dfs1000 = [pd.util.testing.makeDataFrame() for i in range(1000)] 

%timeit reduce(lambda df1, df2: df1.merge(df2, on="A", how='outer'), dfs10) 
10 loops, best of 3: 45.8 ms per loop 
%timeit merge_with_concat(dfs10,"A") 
100 loops, best of 3: 11.7 ms per loop 

%timeit merge_with_concat(dfs100,"A") 
10 loops, best of 3: 139 ms per loop 
%timeit reduce(lambda df1, df2: df1.merge(df2, on="A", how='outer'), dfs100) 
1 loop, best of 3: 1.55 s per loop 

%timeit merge_with_concat(dfs1000,"A") 
1 loop, best of 3: 9.67 s per loop 
%timeit reduce(lambda df1, df2: df1.merge(df2, on="A", how='outer'), dfs1000) 
# I killed it after about 5 minutes so the other one is definitely faster 
+0

謝謝,這是我一直在尋找 – morph

+0

不會'DFS =(df.set_index(COL,滴= TRUE)在DFS DF)'是更多的內存效率的,因爲它是一臺發電機 – muon

+1

@嗯,很棒!在將其更改爲發生器後,我使用'dfs1000'設置了幾個基準測試,似乎在我的系統上運行速度提高了約2.5秒(從9.6降低了7.1秒)。注意,如果你想做這個改變,你應該調用生成器而不是'dfs',因爲你仍然需要在'pd.concat'中爲'keys'參數獲得'dfs'的長度(要合併的數據幀的數量) '和發電機沒有長度。 – bunji