Python Pandas — самые высокие значения из нескольких столбцов дублированных записей

avatar
Albert
8 августа 2021 в 19:53
56
1
1

У меня есть следующий df:

A        B   C
entry1   10  3
entry1   7   5 
entry1   2   NaN
entry2   1   1
entry2   2   4
entry2   3   3  
...  

В столбце A есть повторяющиеся записи, и мне интересно выбрать самые высокие значения из столбцов B и C для каждой записи. Если значение NaN существует, оно перезаписывает самые высокие значения.

Пример:

Для записи 1 я хотел бы сохранить в df только значение 10 в столбце B и NaN в столбце C<454316464.63184618.63184617>634376184.

Для записи2 я хотел бы сохранить в df только значение 3 в столбце B и 4 в столбце C<454376184.6>

Я думал отсортировать значения, а затем выбрать последнее значение следующим образом:

df = df.sort_values(by=['A', 'B', 'C'], ascending=[False, True, True])
print(df.drop_duplicates(subset='A', keep='last'))

Таким образом, оставшаяся запись будет иметь только самое высокое значение для столбца B, а не для столбца C.

Как мне добиться этого?

Спасибо.

Источник
drum
8 августа 2021 в 19:58
0

используйте groupby()

Ответы (1)

avatar
Henry Ecker
8 августа 2021 в 20:00
2

One approach would be to fillna the nan with inf then just take the groupby max чтобы получить максимальное значение для группы. Затем replace inf возвращаются к nan. Это гарантирует, что значение nan будет максимальным для группы, поскольку inf равно:

cols = ['B', 'C']
df[cols] = df[cols].fillna(np.inf)  # replace NaN with largest value
df = df.groupby('A', as_index=False)[cols].max()  # Get Max Per Group
df[cols] = df[cols].replace(np.inf, np.nan)  # Return to NaN

Alternatively use a function or lambda to produce nan if any values ​​are NaN otherwise the max:

df = (
    df.groupby('A', as_index=False)[['B', 'C']]
        .agg(lambda s: np.nan if s.isna().any() else s.max())
)

Оба производят df:

        A   B    C
0  entry1  10  NaN
1  entry2   3  4.0

DataFrame и импорт:

import numpy as np
import pandas as pd

df = pd.DataFrame({
    'A': ['entry1', 'entry1', 'entry1', 'entry2', 'entry2', 'entry2'],
    'B': [10, 7, 2, 1, 2, 3],
    'C': [3.0, 5.0, np.nan, 1.0, 4.0, 3.0]
})
tdy
8 августа 2021 в 20:30
0

как всегда отличный ответ +1. У меня нет времени запускать тайминги в банкомате, но мне любопытны различные варианты. позже попробую сделать тайминг.

Henry Ecker
8 августа 2021 в 20:31
1

@ мне, когда ты это сделаешь, я тоже хотел бы знать. знак равно

Albert
8 августа 2021 в 20:47
0

@HenryEcker: мне очень нравится ваше решение. Спасибо! Только что проверил, работает!

tdy
8 августа 2021 в 21:26
0

@HenryEcker похоже, что есть точка перегиба в ~ 10 000 строк, где groupby.max обгоняет groupby.transform (хотя, похоже, ОП в конечном итоге нуждался в вашем подходе agg)

Henry Ecker
8 августа 2021 в 23:58
1

Спасибо, что запустили те тайминги, которые я всегда хотел бы знать. Ага, конечно, читабельнее, но тоже медленный.