如何将转换应用于熊猫数据框列表?
问题描述:
我有一堆属于少数逻辑分组的熊猫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
使用drop
与inplace=True
超过DataFrames的列表理解列表工程,我预期,但它不与groupby
和agg
列表--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]
更改为drop
的inplace=True
值确实我所期待的东西,但它似乎并没有做出与groupby
和agg
的差异。
有人可以解释为什么这两个列表解析有不同的结果,或让我更好的方式来获得我期待的结果吗?
这是代码将函数映射到DataFrame列表的问题吗?
我一直在阅读熊猫的文档和谷歌搜索了一会儿,并尝试各种东西,如query
,map
,lambda
组合,但无济于事。
答
解决方案
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
]
只是分配一个新的列表,旧列表。
答
如果我正确理解您的问题,问题出在您的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]
您是否尝试过'concatenating'您的数据帧? –
我想让它们保持分离状态,因为它们是不同人群的单独测试,每个数据框稍后需要不同的转换。 – zhespelt
实际上,每个列表和3个列表中大约有10个数据框,但处理有足够的重叠,因此我一次可以将整个列表应用到整个列表中。 – zhespelt