Условие для всех строк группы по

#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