熊猫一次一次多重分组聚合-加速

时间:2018-09-13 21:28:42

标签: python pandas optimization

我必须执行多个transform-groupby-aggregate操作,并且当前正在一个接一个地执行这些操作,但这非常慢:

from pandas.tseries.offsets import MonthEnd
import pandas as pd
fsc = ['E', 'P']
mtx = pd.DataFrame({'EQ': {'2': 'P', '9970': 'P', '9971': 'P'},
'HOURS': {'2': 7.2000000000000002, '9970': 18.0, '9971': 10.0},
'LOC': {'2': 'A', '9970': 'B', '9971': 'B'},
'ORG': {'2': 23, '9970': 52, '9971': 52},
'START': {'2': pd.Timestamp('2014-07-31 17:21:59'),
 '9970': pd.Timestamp('2011-12-15 17:59:59'),
 '9971': pd.Timestamp('2011-08-07 04:59:59')}})

monthly = pd.DataFrame(pd.date_range(start='1970-01-01', end="2017-04-01 23:59:59", freq="MS"))[0].transform(lambda m : (( mtx.loc[(mtx["EQ"].isin(fsc)) & (mtx["START"] >= pd.to_datetime(m)) & (mtx["START"] <= pd.to_datetime(m) + MonthEnd(1))]).groupby(["ORG","LOC"])["HOURS"].mean()))
monthly = monthly.stack().stack().reset_index()
monthly_tmp = pd.DataFrame(pd.date_range(start='1970-01-01', end="2017-04-01 23:59:59", freq="MS"))[0].transform(lambda m : (( mtx.loc[(mtx["EQ"].isin(fsc)) & (mtx["START"] >= pd.to_datetime(m)) & (mtx["START"] <= pd.to_datetime(m) + MonthEnd(1))]).groupby(["ORG","LOC"])["HOURS"].sum()))
monthly = pd.merge(monthly,monthly_tmp.stack().stack().reset_index(),on=["level_0","LOC","ORG"],how="left")

给予:

pd.DataFrame({'0_x': {0: 10.0, 1: 18.0},
'0_y': {0: 10.0, 1: 18.0},
'LOC': {0: 'B', 1: 'B'},
'ORG': {0: 52, 1: 52},
'level_0': {0: 499, 1: 503}}

如何一次完成所有这些操作? 我尝试过:

f = {'HOURS': 'mean','HOURS': 'sum'}
pd.DataFrame(pd.date_range(start='1970-01-01', end="2017-04-01 23:59:59", freq="MS"))[0].transform(lambda m : (( mtx.loc[(mtx["EQ"].isin(fsc)) & (mtx["START"] >= pd.to_datetime(m)) & (mtx["START"] <= pd.to_datetime(m) + MonthEnd(1))]).groupby(["ORG","LOC"]).agg(f)))

但是它以另一种奇怪的方式返回DataFrame。

1 个答案:

答案 0 :(得分:1)

您可以将.agg()与转置一起使用。它不会给您确切的输出,但是您可以在熊猫中进行操作:

.groupby(["ORG","LOC"])['HOURS'].agg(['mean', 'sum']).T.unstack())).stack().stack().stack().reset_index()

所以仅使用您的示例

new_df = pd.DataFrame(pd.date_range(start='1970-01-01', end="2017-04-01 23:59:59", freq="MS"))[0].transform(lambda m : ((mtx.loc[(mtx["EQ"].isin(fsc)) & (mtx["START"] >= pd.to_datetime(m)) & (mtx["START"] <= pd.to_datetime(m) + MonthEnd(1))]).groupby(["ORG","LOC"])['HOURS'].agg(['mean', 'sum']).T.unstack())).stack().stack().stack().reset_index()

您将获得

   level_0  level_1 LOC  ORG     0
0   499     mean    B    52     10.0
1   499     sum     B    52     10.0
2   503     mean    B    52     18.0
3   503     sum     B    52     18.0

不确定该输出是否是您想要的,但是您可以执行以下操作:

new_df['mean'] = new_df[new_df['level_1'] == 'mean'][0]
new_df['sum'] = new_df[new_df['level_1'] == 'sum'][0]
new_df['sum'] = new_df['sum'].shift(-1)
new_df[~new_df['mean'].isna()].drop(columns=['level_1',0])

    level_0 LOC  ORG    mean    sum
0    499     B   52     10.0    10.0
2    503     B   52     18.0    18.0