суммирование всех сумм по дате в отношении отдельных лиц

#python #pandas #bigdata #pandas-groupby #pandasql

#python #pandas #bigdata #pandas-groupby #pandasql

Вопрос:

У меня есть этот фрейм данных

 df:
     payout  person1 person2      date    
1    300.0     LA       NaN     2012-02-01  
2    500.0     DO       NaN     2012-02-01  
3    600.0     DO       NaN     2012-02-01  
4    300.0     DO       NaN     2012-01-01  
5    500.0     DO       NaN     2012-01-01  
6    1000.0    DO       AL      2012-01-01  
7    800.0     DO       AL      2012-01-01 
  

В расширенном фрейме данных мне нужно суммировать все выплаты за каждый уникальный месяц и год для каждого person1 отдельно. Затем, если person2 существует, мне нужно разделить выплату (после суммирования каждого месяца) между person1 и person2.
Вывод должен быть таким:

 df:
         person     date         sum 
    1    LA         2012-02-01    300.0 
    2    DO         2012-02-01    1100.0        
    3    DO         2012-01-01    1700.0
    4    AL         2012-01-01    900.0 
  

Ответ №1:

Возможно, не так элегантно, но работает для этого случая:

 m1=(df[df.person2.isna()].groupby([df.date.dt.date,'person1'])
   .payout.sum().reset_index().rename(columns={'person1':'person'}))

m2=df.dropna().groupby([df.date.dt.date,'person1','person2']).payout.mean().reset_index()

df_new=(m1.merge(m2.melt(['date','payout'],value_name='person').
          drop('variable',1),how='outer').groupby(['date','person'],as_index=False).sum())

print(df_new)

         date person  payout
0  2012-01-01     AL   900.0
1  2012-01-01     DA  1700.0
2  2012-02-01     DA  1100.0
3  2012-02-01     LA   300.0
  

Ответ №2:

вы можете создать столбец, содержащий подходящую сумму для суммирования, если в столбце person2 есть кто-то с np.where

 df['payout_sum'] = np.where(df.person2.notnull(), df.payout/2., df.payout)
  

Затем, используя concat , groupby и pd.Grouper , вы можете получить результат:

 df_tot = (pd.concat([df[['date','person1','payout_sum']].rename(columns={'person1':'person'}),
                     df[['date','person2','payout_sum']].rename(columns={'person2':'person'})
                                                          .dropna()])
            .groupby([pd.Grouper(key='date', freq='MS'),'person'])['payout_sum']
            .sum().reset_index())
print (df_tot)
        date person  payout_sum
0 2012-01-01     AL       900.0
1 2012-01-01     DA      1700.0
2 2012-02-01     DA      1100.0
3 2012-02-01     LA       300.0
  

Интерес pd.Grouper с ‘MS’ заключается в том, что он будет выполнять повторную выборку к началу месяца, в случае, если у вас выплаты в течение нескольких дней в месяце.