#python #pandas #dataframe #pandas-groupby #apply
Вопрос:
Относительно этого типа фрейма данных:
import pandas as pd
import datetime
df = pd.DataFrame({'ID': [1,1,1,1,2,2,2,3],
'Time': [datetime.date(2019, 12, 1), datetime.date(2019, 12, 5),datetime.date(2019, 12, 8),datetime.date(2019, 8, 4),datetime.date(2019, 11, 4),datetime.date(2019, 11, 4),datetime.date(2019, 11, 3),datetime.date(2019, 12, 20)],
'Value':[2,2,2,50,7,100,7,5]})
ID Time Value
0 1 2019-12-01 2
1 1 2019-12-05 2
2 1 2019-12-08 2
3 1 2019-08-04 50
4 2 2019-11-04 7
5 2 2019-11-04 100
6 2 2019-11-03 7
7 3 2019-12-20 5
Меня интересуют только 3 последних значения (относительно времени)
и
Я хотел бы сохранить только идентификаторы, в которых находятся эти 3 значения
Таким образом, мой желаемый результат будет выглядеть следующим образом:
ID
0 1
Действительно, значение 50 для первого идентификатора является четвертым последним значением, так что это неинтересно.
Ответ №1:
Вы могли бы использовать комбинацию query
и groupby
size
:
ids = df.query('Value < 10').groupby('ID')['Time'].size().ge(3)
ids[ids].reset_index().drop('Time', axis=1)
выход:
ID
0 1
Альтернативное использование filter
(медленнее):
df.groupby('ID').filter(lambda g: len(g[g['Value'].lt(10)]['Time'].nlargest(3))>2)
выход:
ID Time Value
0 1 2019-12-01 2
1 1 2019-12-05 2
2 1 2019-12-08 2
3 1 2019-08-04 50
и чтобы получить только идентификатор: добавьте ['ID'].unique()
Комментарии:
1. Я ошибаюсь или фильтрация, прежде чем занять как можно больше времени, может привести к неправильным результатам?
2. Я понял вопрос, так как нам нужно как минимум 3 значения ниже 10 , если это неверно, то довольно легко использовать ту же логику с другим условием
3. Действительно, @rpanai, мы хотели бы просмотреть только 3 последних значения, поэтому, если вы удалите значения при условии, что это не сработает … но пока спасибо за вашу помощь !
4. @mozway на операции написано
3 latest values
. Я тоже был в замешательстве.5. хорошо, тогда два условия нужно поменять местами (сначала возьмите 3 последних, затем удалите значения, наконец, посчитайте), но общая логика аналогична 😉
Ответ №2:
В рамках группы:
- Я сортирую группу по времени
- используйте логическое значение, чтобы определить, соответствует ли условие
- Возьмите только последние 3 значения и суммируйте логическое значение, определенное выше
- Проверьте, точно ли это число равно 3
grp = df.groupby("ID")
.apply(lambda x:
x.sort_values("Time")["Value"].lt(10)[-3:].sum()==3)
grp[grp]
ID
1 True
dtype: bool