#python #pandas
#питон #панды
Вопрос:
У меня есть фрейм данных pandas с датами и значениями.
import pandas as pd df = pd.DataFrame({'date':['11-10','11-10','11-10','12-10','12-10','12-10'], 'id': [1, 1, 2, 1, 1, 2], 'val':[20, 30, 40, 50, 25, 35] })
Я бы хотел, чтобы фильтр фрейма данных включал только верхние и нижние N строк для каждой даты. Допустим, N = 2. Тогда фрейм данных отбросит 1-ю строку 11-10 20
и 5-ю строку 12-10 25
.
Надеясь на решение, которое может масштабироваться для разных значений N
.
Ответ №1:
Вы можете сгруппировать date
фрейм данных, затем вызвать nlargest
val
столбец, передав значение N
:
gt;gt;gt; df.groupby('date')['val'].nlargest(2) date 11-10 2 40 1 30 12-10 3 50 5 35 Name: val, dtype: int64
При необходимости вы можете вызвать to_frame()
результирующую серию, чтобы преобразовать ее в фрейм данных.
Для обновленного вопроса вы все еще можете реализовать приведенный выше код с некоторыми дополнительными работами, чтобы также получить идентификаторы, а затем выполнить внутреннее слияние с исходным фреймом данных:
out= (df.set_index('id') .groupby(['date'])['val'] .nlargest(2) .to_frame('val') .reset_index() .merge(df, how='inner') )
выход:
date id val 0 11-10 2 40 1 11-10 1 30 2 12-10 1 50 3 12-10 2 35
Комментарии:
1. Однако я хотел бы сохранить столбцы в groupby. Когда я запускаю это, я получаю только серию.
2. Вот почему я упомянул, что вы можете дополнительно позвонить
to_frame
, чтобы преобразовать его в фрейм данных, и даже передать имя столбца:df.groupby('date')['val'].nlargest(2).to_frame('val')
3. Я получаю фрейм данных только с одним столбцом,
val
. Столбцы, используемые в groupby, будут потеряны. Я бы хотел их сохранить.4. Вы имеете в виду, что у вас тоже есть дополнительные колонки?
5. Да, у меня есть две колонки
groupby
. Извините, это макет df, размещенный на SO.
Ответ №2:
Вы можете сделать:
index_of_N_greatest_vals = df.groupby('date')['val'].nlargest(N).reset_index()['level_1'] df1 = df[df.index.isin(index_of_N_greatest_vals)]
Выход:
date id val 1 11-10 1 30 2 11-10 2 40 3 12-10 1 50 5 12-10 2 35
Ответ №3:
Один из вариантов состоит в том, чтобы отсортировать столбцы и взять хвост группы.:
(df.sort_values(['date', 'val']) .groupby('date', sort = False) .tail(n=2) ) date id val 1 11-10 1 30 2 11-10 2 40 5 12-10 2 35 3 12-10 1 50