Извлечение строк с n самыми старыми и n самыми новыми датами для каждой группы

#python #pandas

#питон #панды

Вопрос:

Давайте предположим, что у меня есть следующий набор данных в python и pandas :

 Stock_id    Date    Stock_value
1   10/04/2019  2
1   11/04/2019  5
1   12/04/2019  1
1   13/04/2019  9
1   14/04/2019  6
1   15/04/2019  5
1   16/04/2019  7
2   12/04/2019  2
2   13/04/2019  9
2   14/04/2019  2
2   15/04/2019  4
2   16/04/2019  9
 

Теперь я хочу иметь n (2 в моем конкретном примере) строк с самыми старыми датами для каждой группы:

 Stock_id    Date    Stock_value
1   10/04/2019  2
1   11/04/2019  5
2   12/04/2019  2
2   13/04/2019  9
 

Также отдельно я хочу иметь n (2 в моем конкретном примере) строк с самыми новыми датами для каждой группы:

 Stock_id    Date    Stock_value
1   15/04/2019  5
1   16/04/2019  7
2   15/04/2019  4
2   16/04/2019  9
 

Как я могу сделать каждый из них (отдельно) в python и pandas ?

Ответ №1:

Использовать GroupBy.head с GroupBy.tail :

Также необходимо отсортировать даты Stock_id и время , поэтому используйте с to_datetime DataFrame.sort_values :

 df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)
df = df.sort_values(['Stock_id','Date'])

df1 = df.groupby('Stock_id').head(2)
print (df1)
   Stock_id       Date  Stock_value
0         1 2019-04-10            2
1         1 2019-04-11            5
7         2 2019-04-12            2
8         2 2019-04-13            9

df2 = df.groupby('Stock_id').tail(2)
print (df2)
    Stock_id       Date  Stock_value
5          1 2019-04-15            5
6          1 2019-04-16            7
10         2 2019-04-15            4
11         2 2019-04-16            9
 

Решение с nsmallest помощью и nlargest :

 df1 = df.groupby('Stock_id', group_keys=False).apply(lambda x: x.nsmallest(2, 'Date'))
print (df1)
   Stock_id       Date  Stock_value
0         1 2019-04-10            2
1         1 2019-04-11            5
7         2 2019-04-12            2
8         2 2019-04-13            9

df2 = df.groupby('Stock_id', group_keys=False).apply(lambda x: x.nlargest(2, 'Date'))
print (df2)
    Stock_id       Date  Stock_value
6          1 2019-04-16            7
5          1 2019-04-15            5
11         2 2019-04-16            9
10         2 2019-04-15            4
 

Комментарии:

1. Хорошо, спасибо. На самом деле я протестировал это, но у меня это не сработало (он по-прежнему возвращал все даты); затем я увидел, что в моем исходном коде произошла ошибка, и именно поэтому она не сработала, ха-ха.

2. Кстати, как насчет использования nlargest() и nsmallest() ? Если это сработает, вы можете пропустить часть .sort_values, я полагаю?

3. @PoeteMaudit — да, это возможно, но, очевидно, намного медленнее.

4. Хорошо, это звучит хорошо. (кстати, для меня это не так очевидно, но, вероятно, потому, что я не знаю, как именно эти функции pandas работают под капотом).