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



我必须执行多个转换分组聚合操作,并且目前正在一个接一个地执行这些操作,但它非常慢:

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)))

但它以不同的奇怪方式返回数据帧。

您可以将.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

最新更新