我有以下数据框:
Name1 Name2 Month Mode Value1 Value2
A N Sep Plan 9 9
B N Nov Plan 6 6
B N Jan Plan 6 6
C N Feb Actual 4 4
C N Jul Actual 3 3
D N May Plan 2 2
E N Apr Actual 6 6
F N Feb Actual 7 7
E N May Actual 4 4
F N Jun Plan 3 3
<+ 100 more rows>
考虑当前月份为6月,则预期输出如下:
Name1 Name2 Mode Value1 Value2
C N Actual 4 4
D N Plan 2 2
E N Actual 10 10
F N Actual 7 7
F N Plan 3 3
在这里,我已经从2月:当前月(在本例中为6月)开始按月对行进行过滤,然后对每个模式进行分组以查找所有名称。 (例如:F仅实际使用一次,而计划仅使用一次)
我以前尝试过对列进行转置,然后使用以下内容汇总直到当前月份的数据:
df = pd.DataFrame({'Name1':df['Name1'], 'previous_mt':df.loc[:,prev_month], 'current_mt':df.loc[:,this_month]})
其中:
prev = curr_month.replace(day=1) - timedelta(days=1)
prev_month = prev.strftime("%B")[:3]
curr_month = dt.datetime.now()
this_month = curr_month.strftime("%B")[:3]
但是,这变得非常复杂,因为实际数据具有很多模式,而且还有很多年的数据。有没有一种更简单的解决方案可以避免这种并发症并可以实现类似的解决方案?
最后,我希望具有以下数据框:
Name1 Name2 Actual_Value1 Actual_Value2 Plan_Value1 Plan_Value1
C N 4 4
D N 2 2
E N 10 10
F N 7 7 3 3
我猜我可以在pandas中使用pivot_table使用这种格式:
df=pd.pivot_table(df_input,index=['Name1', 'Name2'],
columns=['Mode'],
values=['Value1', 'Value2'],
aggfunc=np.sum, fill_value=0).reset_index().rename_axis(1)
答案 0 :(得分:1)
基于示例数据集,此代码提供了您正在寻找的结果:
lstAllMonths=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
curMth = datetime.today().month # 7=July
curMth = 6 # Jun for testing
lstMth = lstAllMonths[1:curMth]
df = df[df['Month'].isin(lstMth)][['Name1','Name2','Mode','Value1','Value2']]
gb = df.groupby(['Name1','Name2','Mode'])
dfagg = gb.agg({'Value1':sum, 'Value2':sum})
dfpvt = pd.pivot_table(dfagg,index=['Name1', 'Name2'],
columns=['Mode'],
values=['Value1', 'Value2'],
aggfunc=np.sum, fill_value=0).reset_index().rename_axis(1)
dfpvt.columns=['Name1','Name2','Actual_Value1','Plan_Value1','Actual_Value2','Plan_Value2']
dfpvt.replace(0,'', inplace=True)
dfpvt = dfpvt[['Name1','Name2','Actual_Value1','Actual_Value2','Plan_Value1','Plan_Value2']]
print(dfpvt)