Как сделать groupby max для создания новых столбцов в pandas датафрейме - PullRequest
4 голосов
/ 13 января 2020

У меня есть датафрейм, как показано ниже, к которому я хочу применить sql logi c, который упоминается ниже

df.head(25)

ORDER_ID    CODE    STATUS_DATE                       RNK
19837715    0400    22/10/19 08:11:08.000000000 AM GMT  2
19837715    0400    22/10/19 10:00:03.000000000 AM GMT  1
19837715    0400    22/10/19 10:47:08.000000000 AM GMT  3
19837715    0500    22/10/19 10:00:00.000000000 AM GMT  1
19837715    1100    01/11/19 10:02:00.000000000 AM GMT  1
19837715    1240    02/11/19 08:00:00.000000000 AM GMT  1
19837833    0400    22/10/19 08:13:09.000000000 AM GMT  3
19837833    0400    22/10/19 08:22:09.000000000 AM GMT  4
19837833    0400    23/10/19 04:30:10.000000000 AM GMT  1
19837833    0400    23/10/19 09:30:07.000000000 PM GMT  2
19837833    0500    23/10/19 01:08:00.000000000 AM GMT  1
19837833    0500    23/10/19 04:30:00.000000000 AM GMT  3
19840750    0500    23/10/19 12:30:00.000000000 PM GMT  1
19840750    1100    01/11/19 10:06:02.000000000 AM GMT  1
19840750    1240    02/11/19 08:40:05.000000000 AM GMT  1
19840750    1305    05/11/19 07:21:03.000000000 AM GMT  2
19840750    1305    05/11/19 08:22:03.000000000 AM GMT  1
19840750    1400    09/11/19 06:13:12.000000000 AM GMT  3

Я хочу применить ниже sql logi c к этому фрейму данных.

select
    order_id
    , TRUNC(MAX(decode(df.code, '0400', STATUS_DATE, Null))) act_0400
    , TRUNC(MAX(decode(df.code, '0500', STATUS_DATE, Null))) act_0500
from
    dataframe df  
where 
      df.rnk =1 
group by    
    order_id

Здесь я пытаюсь создать новые столбцы act_0400 и Act_0500, беря максимальное значение даты из столбца даты состояния для условия ранга = 1 и группируя их на основе идентификатора заказа

Ожидаемый результат

ORDER_ID    ACT_0400    ACT_0500
19837715    22/10/2019  22/10/2019
19837833    23/10/2019  23/10/2019
19840750                23/10/2019

Как это можно сделать в pandas

Ответы [ 3 ]

2 голосов
/ 13 января 2020

Вот способ сделать:

codes = [400, 500]
df1 = (df
     .query("CODE in @codes and RNK == 1")
     .groupby(['ORDER_ID','CODE'])['STATUS_DATE']
     .first()
     .unstack())

# fix column names
df1.columns.name = None
df1 = df1.add_prefix('ACT_').reset_index()

   ORDER_ID     ACT_400     ACT_500
0  19837715  2019-10-22  2019-10-22
1  19837833  2019-10-23  2019-10-23
2  19840750         NaN  2019-10-23
2 голосов
/ 13 января 2020

Вы можете сначала преобразовать STATUS_DATE в дату по to_datetime с Series.dt.date, затем отфильтровать по boolean indexing с Series.isin и последнее изменение на DataFrame.pivot_table с совокупностью max, последняя очистка некоторых данных на DataFrame.rename_axis, DataFrame.rename_axis и DataFrame.reset_index:

df['STATUS_DATE'] = pd.to_datetime(df['STATUS_DATE']).dt.date
df = (df[(df['RNK'] == 1) & df['CODE'].isin([400,500])]
        .pivot_table(index="ORDER_ID", columns="CODE", values="STATUS_DATE", aggfunc='max')
        .rename_axis(None, axis=1)
        .add_prefix('ACT_')
        .reset_index())
print (df)
   ORDER_ID     ACT_400     ACT_500
0  19837715  2019-10-22  2019-10-22
1  19837833  2019-10-23  2019-10-23
2  19840750         NaN  2019-10-23
1 голос
/ 13 января 2020

Вы можете сделать, как показано ниже

a = df.loc[df['RNK']==1 & (df['CODE']==400) | (df['CODE']==500)]
a.pivot(index="ORDER_ID", columns="CODE", values="STATUS_DATE").add_prefix('ACT_').reset_index().rename_axis(None, axis=1)

Выход

    ORDER_ID    ACT_400     ACT_500
0   19837715    22/10/19    22/10/19
1   19837833    23/10/19    23/10/19
2   19840750        NaN     23/10/19
...