2016-05-14 115 views
1

我有一堆屬於少數邏輯分組的熊貓DataFrames,但所有這些都有一些重疊的列。如果我可以將一系列函數(如下面的funcs中的函數)應用於DataFrame的整個列表,那將節省大量時間。如何將轉換應用於熊貓數據框列表?

# Make example DataFrames 
df_a = pd.DataFrame({'col_a': [1, 1, 2], 'col_b': [1, 1, 2], 'col_c': [1, 1, 2], 
        'col_d': [1, 2, 3], 'col_e': [1, 2, 3], 'col_f': [1, 2, 3], 
        'foo': 'foo', 'bar': 'bar', 'baz': 'baz'}) 
df_b = pd.DataFrame({'col_a': [4, 5, 5], 'col_b': [4, 5, 5], 'col_c': [4, 5, 5], 
        'col_d': [4, 5, 6], 'col_e': [4, 5, 6], 'col_f': [4, 5, 6], 
        'foo': 'foo', 'bar': 'bar', 'baz': 'baz'}) 
df_c = pd.DataFrame({'col_a': [7, 7, 7], 'col_b': [7, 7, 7], 'col_c': [7, 7, 7], 
        'col_d': [7, 8, 9], 'col_e': [7, 8, 9], 'col_f': [7, 8, 9], 
        'foo': 'foo', 'bar': 'bar', 'baz': 'baz'}) 

# Make list of a bunch of DataFrames 
data_sets_a = [df_a, df_b, df_c] 

# Drop some columns (this works as expected on each DataFrame) 
[d.drop(['foo', 'bar', 'baz'], axis=1, inplace=True) for d in data_sets_a] 

# List of functions to apply to overlapping DataFrame columns 
funcs = {'col_d': 'count', 'col_e': 'min', 'col_f': 'sum'} 

# Group by and aggregate with funcs dict (does not work) 
[d.groupby(['col_a', 'col_b', 'col_c']).agg(funcs, inplace=True).reset_index() for d in data_sets_a] 

data_sets_a 

使用dropinplace=True超過DataFrames的列表理解列表工程,我預期,但它不與groupbyagg列表--the DataFrames保持不變工作。

[ col_a col_b col_c col_d col_e col_f 
0  1  1  1  1  1  1 
1  1  1  1  2  2  2 
2  2  2  2  3  3  3, 
    col_a col_b col_c col_d col_e col_f 
0  4  4  4  4  4  4 
1  5  5  5  5  5  5 
2  5  5  5  6  6  6, 
    col_a col_b col_c col_d col_e col_f 
0  7  7  7  7  7  7 
1  7  7  7  8  8  8 
2  7  7  7  9  9  9] 

更改爲dropinplace=True值確實我所期待的東西,但它似乎並沒有做出與groupbyagg的差異。

有人可以解釋爲什麼這兩個列表解析有不同的結果,或讓我更好的方式來獲得我期待的結果嗎?

這是代碼將函數映射到DataFrame列表的問題嗎?

我一直在閱讀熊貓的文檔和谷歌搜索了一會兒,並嘗試各種東西,如query,map,lambda組合,但無濟於事。

+0

您是否嘗試過'concatenating'您的數據幀? –

+0

我想讓它們保持分離狀態,因爲它們是不同人羣的單獨測試,每個數據框稍後需要不同的轉換。 – zhespelt

+0

實際上,每個列表和3個列表中大約有10個數據框,但處理有足夠的重疊,因此我一次可以將整個列表應用到整個列表中。 – zhespelt

回答

1

解決方案

for i in range(len(data_sets_a)): 
    cols = ['col_a', 'col_b', 'col_c'] 
    gb = data_sets_a[i].groupby(cols) 
    data_sets_a[i] = gb.agg(funcs, inplace=1).reset_index() 

說明

如果列表理解,你返回正確的對象,但不能將其放置在那裏你想要的。 inplace=True不是增加列表data_sets_a中指向的同一對象。

我所做的是爲列表的每個元素分配正確的擴充。

另一種方式做它是使用你已經有了什麼:

data_sets_a = [ 
    d.groupby(
     ['col_a', 'col_b', 'col_c'] 
    ).agg(funcs, inplace=True).reset_index() for d in data_sets_a 
] 

只是分配一個新的列表,舊列表。

1

如果我正確理解您的問題,問題出在您的funcs。你可以嘗試一下這種方式來代替:

def funcs(x): 
    col_d = x['col_d'].count() 
    col_e = x['col_e'].min() 
    col_f = x['col_f'].sum() 
    return pd.Series([col_d, col_e, col_f], index= ['col_d', 'col_e', 'col_f']) 

然後你可以使用apply(funcs)

[d.groupby(['col_a', 'col_b', 'col_c']).apply(funcs).reset_index() for d in data_sets_a] 

輸出將是:

[ col_a col_b col_c col_d col_e col_f 
0  1  1  1  2  1  3 
1  2  2  2  1  3  3, 
    col_a col_b col_c col_d col_e col_f 
0  4  4  4  1  4  4 
1  5  5  5  2  5  11, 
    col_a col_b col_c col_d col_e col_f 
0  7  7  7  3  7  24] 
相關問題