Как преобразовать строку даты в datetime в функции agg во время группового - PullRequest
2 голосов
/ 16 октября 2019

При заданном кадре данных, как группировать Item со значением max Updated Date (как datetime вместо строки даты) при сохранении формата строки даты в кадре данных результата ?

df = pd.DataFrame([['A', 10, 'Jun 12, 2019 06:16 PM'],
                  ['A', 20, 'Jul 26, 2019 10:56 AM'],
                  ['B', 30, 'May 20, 2019 05:54 PM'],
                  ['B', 40, 'Apr 28, 2019 06:42 PM']],
                  columns=['Item', 'Quantity', 'Updated Date'])
>>> df
  Item  Quantity           Updated Date
0    A        10  Jun 12, 2019 06:16 PM
1    A        20  Jul 26, 2019 10:56 AM
2    B        30  May 20, 2019 05:54 PM
3    B        40  Apr 28, 2019 06:42 PM

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

  Item  Quantity           Updated Date
0    A        30  Jul 26, 2019 10:56 AM
1    B        70  May 20, 2019 05:54 PM

То, что я пробовал

Если я поставлю 'Updated Date': max в agg(), он просто вернул бы максимальное значение в алфавитном порядке

>>> df.groupby(['Item'], as_index=False).agg({'Quantity': sum, 'Updated Date': max})
  Item  Quantity           Updated Date
0    A        30  Jun 12, 2019 06:16 PM   # expected to be Jul 26
1    B        70  May 20, 2019 05:54 PM

Если применить pd.to_datetime(), это даст мне более близкий результат, но формат строки даты будет искажен

df['Updated Date'] = pd.to_datetime(df['Updated Date'])
df.groupby(['Item'], as_index=False).agg({'Quantity': sum, 'Updated Date': max})
  Item  Quantity        Updated Date
0    A        30 2019-07-26 10:56:00
1    B        70 2019-05-20 17:54:00

можно применять pd.to_datetime() только в течение groupby? Проблема здесь в том, что формат даты и времени не гарантированно будет «% b% d,% Y% I:% M% p», в то время как я хочу сохранить строку даты как есть в результате.

Ответы [ 3 ]

2 голосов
/ 16 октября 2019

Используйте datetime просто как ссылку для ваших сравнений.

g = (df.assign(date=pd.to_datetime(df['Updated Date']))
    .groupby('Item')
    .agg({'Quantity': 'sum', 'date': 'idxmax'}))

g['Updated Date'] = df.loc[g.date, 'Updated Date'].tolist()

      Quantity           Updated Date
Item                                 
A           30  Jul 26, 2019 10:56 AM
B           70  May 20, 2019 05:54 PM
1 голос
/ 16 октября 2019

Конвертировать в datetime и использовать idxmax - это путь. Вам не нужно менять свой фрейм данных, например:

# these are the index of the max dates
s = pd.to_datetime(df['Updated Date']).groupby(df['Item']).idxmax()

(df.groupby('Item')[['Quantity']].sum()        # get the sum of quantity
   .merge(df.loc[s, ['Item','Updated Date']],  # merge with the original rows for dates
          on='Item'                            # on the Item of course
          )
)

Вывод:

  Item  Quantity           Updated Date
0    A        30  Jul 26, 2019 10:56 AM
1    B        70  May 20, 2019 05:54 PM
0 голосов
/ 16 октября 2019

вы можете сделать это используя лямбду, как показано ниже

df = pd.DataFrame([['A', 10, 'Jun 12, 2019 06:16 PM'],
                  ['A', 20, 'Jul 26, 2019 10:56 AM'],
                  ['B', 30, 'May 20, 2019 05:54 PM'],
                  ['B', 40, 'Apr 28, 2019 06:42 PM']],
                  columns=['Item', 'Quantity', 'Updated Date'])

df.groupby(['Item'], as_index=False).agg({'Quantity': sum, 'Updated Date': lambda g: g.loc[pd.to_datetime(df["Updated Date"]).idxmax()]})

или не используя функцию применения, такую ​​как

df["Updated Date 2"] = pd.to_datetime(df["Updated Date"])
result = df.groupby(['Item'], as_index=False).agg({'Quantity': sum, 'Updated Date 2': "idxmax"})
result["Updated Date"] = df["Updated Date"].loc[result["Updated Date 2"]].values
result.drop(columns="Updated Date 2", inplace=True)
result

...