Pandas groupby преобразует максимальное решение?

avatar
Coel Locandro
9 августа 2021 в 02:57
320
2
1

Контекст:

Столбцы моего фрейма данных: идентификаторы (с дубликатами) в A, значения времени B и строковые значения C

Мне нужно обновить все значения C, где C соответствует самому последнему времени B для каждого идентификатора A.

Показывает последнее время для идентификатора (или группы идентификаторов), но не включает значения C:

df.groupby(['A'], as_index=False)['B'].max()

Моя неудачная попытка после того, как я наткнулся на .transform():

df['C'] = df.groupby('A')['B'].transform(['C'].max())
AttributeError: 'list' object has no attribute 'max'

Данные

'a':['zx5','zx5','ab1','ab1','mn3','mn3'],
'b':['1/1/2021','1/2/2021','1/3/2021','1/4/2021','1/5/2021','1/4/2021'],
'c':['aaa','bbb','ccc','ddd','eee','fff']

Желаемый результат:

'a':['zx5','zx5','ab1','ab1','mn3','mn3'],
'b':['1/1/2021','1/2/2021','1/3/2021','1/4/2021','1/5/2021','1/4/2021'],
'c':['bbb','bbb','ddd','ddd','eee','eee']

Если применимо, я ищу эффективное решение, поскольку оно состоит из CSV-файлов с более чем 100 000 строк данных.

Изменить: Из-за комментариев я обновил идентификаторы (A), чтобы они были менее упрощенными, рассматривая их как случайные буквенно-цифровые значения, где сортировка не дает преимуществ

Источник

Ответы (2)

avatar
Henry Ecker
9 августа 2021 в 03:11
0

Мы можем преобразовать b to_datetime Если нет (для правильного поведения сортировки), то, то есть, то есть, то есть 3643253325058> <36431953225050555050505055555325325325058>. groupby transform и пусть выравнивание индекса правильно свяжет значения:

# df['b'] = pd.to_datetime(df['b'])  # Convert to_datetime if not already

df['c'] = df.sort_values('b').groupby('a')['c'].transform('last')

df:

     a          b    c
0  zx5 2021-01-01  bbb
1  zx5 2021-01-02  bbb
2  ab1 2021-01-03  ddd
3  ab1 2021-01-04  ddd
4  mn3 2021-01-05  eee
5  mn3 2021-01-04  eee

Некоторые тайминги через %timeit:

%timeit df.sort_values('b').groupby('a')['c'].transform('last')
275 µs ± 6.23 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df['a'].map(df.sort_values(by='b').groupby('a')['c'].last())
322 µs ± 8.28 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
mozway
9 августа 2021 в 03:21
1

Это вполне нормально, что преобразование выполняется быстрее, оно должно проходить по строкам только один раз ;) Просто подумал об этом после того, как вы опубликовали

Coel Locandro
9 августа 2021 в 03:34
0

@HenryEcker ValueError: невозможно выполнить переиндексацию с повторяющейся оси

Henry Ecker
9 августа 2021 в 03:37
0

Я не понимаю этого с предоставленными образцами данных. Можете ли вы предоставить образец, который делает?

Coel Locandro
9 августа 2021 в 03:47
1

@HenryEcker df.reset_index(inplace=True) исправил мою проблему, tyvm

avatar
mozway
9 августа 2021 в 03:08
1

Вы можете отсортировать по 'a'+'b', сохранить самые последние 'b' для каждой группы 'a' и использовать это для сопоставления данных нового столбца 'c':

keys = df.sort_values(by='b').groupby('a')['c'].last()
df['c'] = df['a'].map(keys)

выход:

    a          b    c
0  A1 2021-01-01  bbb
1  A1 2021-01-02  bbb
2  A2 2021-01-03  ddd
3  A2 2021-01-04  ddd
4  A3 2021-01-05  eee
5  A3 2021-01-04  eee
mozway
9 августа 2021 в 03:17
0

Спасибо @HenryEcker, я только что заметил;)

Coel Locandro
9 августа 2021 в 03:18
0

@mozway Я обновил идентификаторы, считайте их случайными буквенно-цифровыми значениями - сортировка здесь нам не поможет

mozway
9 августа 2021 в 03:18
0

Ну, вы можете сортировать только по "б"