Python: получение строки, которая имеет максимальное значение в группах с помощью groupby
Я надеюсь, что смогу найти помощь на мой вопрос. Я ищу решение для следующей проблемы:
у меня есть фрейм данных, как:
Sp Mt Value count
0 MM1 S1 a **3**
1 MM1 S1 n 2
2 MM1 S3 cb 5
3 MM2 S3 mk **8**
4 MM2 S4 bg **10**
5 MM2 S4 dgd 1
6 MM4 S2 rd 2
7 MM4 S2 cb 2
8 MM4 S2 uyi **7**
моя цель-получить результирующие строки, количество которых равно max между группами, например:
0 MM1 S1 a **3**
1 3 MM2 S3 mk **8**
4 MM2 S4 bg **10**
8 MM4 S2 uyi **7**
кто-то знает, как я могу это сделать в панд или в python?
обновление
Я не дал больше деталей для моего вопроса. Для моей проблемы я хочу сгруппироваться по ['Sp', 'Mt']. Давайте возьмем второй пример:
Sp Mt Value count
4 MM2 S4 bg 10
5 MM2 S4 dgd 1
6 MM4 S2 rd 2
7 MM4 S2 cb 8
8 MM4 S2 uyi 8
для приведенного выше примера я хочу получить все строки, где количество равно max в каждой группе, например:
MM2 S4 bg 10
MM4 S2 cb 8
MM4 S2 uyi 8
7 ответов:
In [1]: df Out[1]: Sp Mt Value count 0 MM1 S1 a 3 1 MM1 S1 n 2 2 MM1 S3 cb 5 3 MM2 S3 mk 8 4 MM2 S4 bg 10 5 MM2 S4 dgd 1 6 MM4 S2 rd 2 7 MM4 S2 cb 2 8 MM4 S2 uyi 7 In [2]: df.groupby(['Mt'], sort=False)['count'].max() Out[2]: Mt S1 3 S3 8 S4 10 S2 7 Name: count
чтобы получить индексы исходного DF вы можете сделать:
In [3]: idx = df.groupby(['Mt'])['count'].transform(max) == df['count'] In [4]: df[idx] Out[4]: Sp Mt Value count 0 MM1 S1 a 3 3 MM2 S3 mk 8 4 MM2 S4 bg 10 8 MM4 S2 uyi 7
обратите внимание, что если у вас есть несколько максимальных значений для каждой группы, все будут возвращены.
обновление
на Аве Мария шанс, что это то, что ОП просит:
In [5]: df['count_max'] = df.groupby(['Mt'])['count'].transform(max) In [6]: df Out[6]: Sp Mt Value count count_max 0 MM1 S1 a 3 3 1 MM1 S1 n 2 3 2 MM1 S3 cb 5 8 3 MM2 S3 mk 8 8 4 MM2 S4 bg 10 10 5 MM2 S4 dgd 1 10 6 MM4 S2 rd 2 7 7 MM4 S2 cb 2 7 8 MM4 S2 uyi 7 7
вы можете отсортировать фрейм данных по количеству, а затем удалить дубликаты. Я думаю, что это проще:
df.sort_values('count', ascending=False).drop_duplicates(['Sp','Mt'])
попробовав решение, предложенное Желязны на относительно большом фрейме данных (~400k строк), я обнаружил, что это очень медленно. Вот альтернатива, которую я нашел, чтобы работать на порядки быстрее в моем наборе данных.
df = pd.DataFrame({ 'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4', 'MM4'], 'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'], 'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'], 'count' : [3,2,5,8,10,1,2,2,7] }) df_grouped = df.groupby(['sp', 'mt']).agg({'count':'max'}) df_grouped = df_grouped.reset_index() df_grouped = df_grouped.rename(columns={'count':'count_max'}) df = pd.merge(df, df_grouped, how='left', on=['sp', 'mt']) df = df[df['count'] == df['count_max']]
простое решение было бы применить: функция idxmax () для получения индексов строк с максимальными значениями. Это позволит отфильтровать все строки с максимальным значением в группе.
In [365]: import pandas as pd In [366]: df = pd.DataFrame({ 'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4','MM4'], 'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'], 'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'], 'count' : [3,2,5,8,10,1,2,2,7] }) In [367]: df Out[367]: count mt sp val 0 3 S1 MM1 a 1 2 S1 MM1 n 2 5 S3 MM1 cb 3 8 S3 MM2 mk 4 10 S4 MM2 bg 5 1 S4 MM2 dgb 6 2 S2 MM4 rd 7 2 S2 MM4 cb 8 7 S2 MM4 uyi ### Apply idxmax() and use .loc() on dataframe to filter the rows with max values: In [368]: df.loc[df.groupby(["sp", "mt"])["count"].idxmax()] Out[368]: count mt sp val 0 3 S1 MM1 a 2 5 S3 MM1 cb 3 8 S3 MM2 mk 4 10 S4 MM2 bg 8 7 S2 MM4 uyi ### Just to show what values are returned by .idxmax() above: In [369]: df.groupby(["sp", "mt"])["count"].idxmax().values Out[369]: array([0, 2, 3, 4, 8])
для меня самым простым решением было бы сохранить значение, когда счетчик будет равен максимальному. Поэтому достаточно одной строчной команды:
df[df['count'] == df.groupby(['Mt'])['count'].transform(max)]
использовать
groupby
иidxmax
методы:
передача col
date
доdatetime
:df['date']=pd.to_datetime(df['date'])
получить индекс
max
колонкиdate
, послеgroupyby ad_id
:idx=df.groupby(by='ad_id')['date'].idxmax()
получить нужные данные:
df_max=df.loc[idx,]
из[54]:
ad_id price date 7 22 2 2018-06-11 6 23 2 2018-06-22 2 24 2 2018-06-30 3 28 5 2018-06-22
df = pd.DataFrame({ 'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4','MM4'], 'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'], 'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'], 'count' : [3,2,5,8,10,1,2,2,7] }) df.groupby(['sp', 'mt']).apply(lambda grp: grp.nlargest(1, 'count'))