Примените расчет к данным, возникающим перед текущей строкой в Pandas Groupby

#python #pandas

Вопрос:

У меня есть следующий фрейм данных:

 import pandas as pd
#Create DF
d = { 
     'Date': ['1/01/2021','2/01/2021','3/01/2021','4/01/2021','5/01/2021','6/01/2021','7/01/2021','8/01/2021','9/01/2021','10/01/2021','11/01/2021','12/01/2021','13/01/2021',
'14/01/2021','15/01/2021','16/01/2021'],
    'Name': ['Joe','Joe','Joe','Joe','Joe','Joe','Joe','Joe','Joe','John','John','John','John','John','John','John'],
    'Criteria':[30,35,2.5,3,6,15,20,1.5,4,25,50,75,2,4,9,2],
    }

              
df = pd.DataFrame(data=d)
df['Date'] = pd.to_datetime(df.Date,format='%d/%m/%Y')
df = df.sort_values('Date')
df

      Date     Name   Criteria
0   2021-01-01  Joe     30.0
1   2021-01-02  Joe     35.0
2   2021-01-03  Joe     2.5
3   2021-01-04  Joe     3.0
4   2021-01-05  Joe      6.0
5   2021-01-06  Joe     15.0
6   2021-01-07  Joe     20.0
7   2021-01-08  Joe     1.5
8   2021-01-09  Joe     4.0
9   2021-01-10  John    25.0
10  2021-01-11  John    50.0
11  2021-01-12  John    75.0
12  2021-01-13  John    2.0
13  2021-01-14  John    4.0
14  2021-01-15  John    9.0
15  2021-01-16  John    2.0
 

Я использую это в модели машинного обучения и хочу создать рейтинг по группам, но включать в него только то, что было до предыдущего дня (т. Е. Чтобы модель не знала будущих значений).

Я ранее использовал:

 df['Rank'] = df.groupby(['Name'])['Criteria'].rank(pct=True, ascending=False)
 

Однако это включает в себя все будущие строки для конкретной группы.

Как я могу настроить эту функцию так, чтобы она рассчитывала что-либо только за день до этого и далее?

Ожидаемый результат (без использования процентиля):

 df['Rank'] = df.groupby(['Name'])['Criteria'].rank(ascending=False)

       Date    Name   Criteria       Rank
0   2021-01-01  Joe     30.0      NA
1   2021-01-02  Joe     35.0      1
2   2021-01-03  Joe     2.5       1
3   2021-01-04  Joe     3.0       2
4   2021-01-05  Joe      6.0      3
5   2021-01-06  Joe     15.0      4
6   2021-01-07  Joe     20.0      5
7   2021-01-08  Joe     1.5       1
8   2021-01-09  Joe     4.0       4
9   2021-01-10  John    25.0      1
10  2021-01-11  John    50.0      2
11  2021-01-12  John    75.0      3
12  2021-01-13  John    2.0       1
13  2021-01-14  John    4.0       2
14  2021-01-15  John    9.0       3
15  2021-01-16  John    2.0       2
 

Большое спасибо!

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

1. Пожалуйста, отредактируйте свой вопрос и укажите ожидаемый результат.

2. Обновлено @ShubhamSharma

3. Все еще неясно, как вы получили ожидаемый результат, не могли бы вы объяснить немного подробнее?

4. Например, индексируйте строку 6. У Джо Criteria число 6. Рейтинг таков 3 , потому что он третий по величине из индексных строк 0:5 (которые являются всеми строками, сгруппированными по Джо и происходящими до даты). Это помогает? Спасибо! @Шубхамшарма

Ответ №1:

В принципе, вы могли бы просто выполнить groupby для подмножества фрейма данных, вместо того, чтобы применять его ко всему фрейму данных.

Поскольку у вас есть Date столбец, содержащий дату наблюдения для каждой точки данных, вы можете в основном создать свое подмножество на основе этого столбца.

Допустим, у вас есть bound переменная, которая содержит ограничение между прошлыми датами (используемыми для обучения) и будущими датами (используемыми для тестирования / проверки), вы можете ограничить полный набор данных меньшим, используя :

 bound = # Some date which splits the dataset in two
df_subset = df.loc[df["Date"] < bound]
df['Rank'] = df_subset.groupby(['Name'])['Criteria'].rank(pct=True, ascending=False)
 

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

1. Спасибо, Алекторкс. Можно ли было бы получить пример этого, используя мои данные? Я не уверен, что вы имеете в виду под limit переменной

2. Ну, что я вижу, так это то, что у вас есть Date столбец, который, я полагаю, представляет дату наблюдения для каждой точки данных. Поскольку вы пытаетесь построить прогностическую модель, предположим, что есть день, который представляет собой предел между прошлыми точками данных (используемыми для обучения) и будущими точками данных (используемыми для тестирования / проверки). Тогда limit переменной будет индекс наступления этой конкретной даты. Имеет ли это смысл для вас ?

3. Tahnks @AlexTorx. В моем примере Date это не индекс, но, по сути, я хотел бы ограничить ранг всеми строками, которые имеют значение a Date до текущей даты. Так что же в таком случае limit будет Date minus 1 day ?

4. Точно! Я обновлю свой ответ, чтобы сделать его более точным в отношении вашего конкретного случая.

5. Спасибо, я сейчас это проверю!