#python #pandas #dataframe
Вопрос:
У меня есть набор данных о киберспорте, подобный этому:
(сделано с использованием pd.to_clipboard()
Week Team Vs Team Points Vs Points
0 1 Team1 Team2 94 67
1 1 Team3 Team4 51 83
2 1 Team5 Team6 74 96
3 1 Team2 Team1 67 94
4 1 Team4 Team3 83 51
5 1 Team6 Team5 96 74
6 2 Team2 Team6 63 76
7 2 Team1 Team3 90 84
8 2 Team4 Team5 68 56
9 2 Team6 Team2 76 63
10 2 Team3 Team1 84 90
11 2 Team5 Team4 56 68
12 3 Team5 Team2 63 74
13 3 Team1 Team6 63 99
14 3 Team3 Team4 50 75
15 3 Team2 Team5 74 63
16 3 Team6 Team1 99 63
17 3 Team4 Team3 75 50
18 4 Team6 Team4 78 91
19 4 Team5 Team1 70 71
20 4 Team2 Team3 99 74
21 4 Team4 Team6 91 78
22 4 Team1 Team5 71 70
23 4 Team6 Team4 78 91
Я хочу создать фрейм данных, который, по сути, для каждой команды каждую неделю создает скользящее среднее значение по игре X из набранных очков. (X может быть 2, 3, 4 и т. Д.). Несколько заметок:
- В этом примере показаны только точки, фактические данные содержат около 10 функций, для которых требуются скользящие средние
- В идеале это была бы функция, поэтому я мог бы поменять X на любое заданное число
- Не каждая команда играет каждую неделю!
Я попытался создать эту функциональность, используя приведенный ниже код:
import pandas as pd
x = pd.read_clipboard()
teams = list(set(x['Team'].to_list() (x['Vs'].to_list())))
res = []
for team in teams:
temp = x.loc[x['Team']==team]
temp.sort_values(by=['Week'], inplace=True)
temp.groupby(['Week']).rolling(2).mean()
res.append(temp)
res_df = pd.concat(res)
Однако это дает такие результаты, как:
Week Team Vs Team Points Vs Points
1 1 Team3 Team4 51 83
10 2 Team3 Team1 84 90
14 3 Team3 Team4 50 75
4 1 Team4 Team3 83 51
8 2 Team4 Team5 68 56
17 3 Team4 Team3 75 50
21 4 Team4 Team6 91 78
2 1 Team5 Team6 74 96
11 2 Team5 Team4 56 68
12 3 Team5 Team2 63 74
19 4 Team5 Team1 70 71
5 1 Team6 Team5 96 74
9 2 Team6 Team2 76 63
16 3 Team6 Team1 99 63
18 4 Team6 Team4 78 91
23 4 Team6 Team4 78 91
0 1 Team1 Team2 94 67
7 2 Team1 Team3 90 84
13 3 Team1 Team6 63 99
22 4 Team1 Team5 71 70
3 1 Team2 Team1 67 94
6 2 Team2 Team6 63 76
15 3 Team2 Team5 74 63
20 4 Team2 Team3 99 74
В то время как я хотел бы, чтобы это выглядело так:
Week Team 2Game_Average_Points
0 1 Team1
1 1 Team2
2 1 Team3
3 1 Team4
4 1 Team5
5 1 Team6
6 2 Team1 94.0
7 2 Team2 67.0
8 2 Team3 51.0
9 2 Team4 83.0
10 2 Team5 74.0
11 2 Team6 96.0
12 3 Team1 92.0
13 3 Team2 65.0
14 3 Team3 67.5
15 3 Team4 78.5
16 3 Team5 65.0
17 3 Team6 86.0
18 4 Team1 76.5
19 4 Team2 68.5
20 4 Team3 67.5
21 4 Team4 78.5
22 4 Team5 59.5
23 4 Team6 87.5
Что я делаю не так? Как я могу достичь желаемого результата?
Комментарии:
1. что происходит с очками команды vs? они тоже учитываются?
2. Команда 1 94 ? должно ли это быть 93 = 94 92 /2 ?
3. Извините. Я потерял подключение к Интернету. Каждая игра представлена в данных двумя способами: таким образом, для каждой игры будет две строки, где идентификатор каждой команды указан в team @Mohammad
4. @Ошибка опечатки БЕНИ с моей стороны, я делаю это вручную
Ответ №1:
>>> roll = df.groupby('Team')[['Team Points']].apply(lambda x: x.rolling(2).mean())
>>> df[['Week', 'Team']].join(roll.rename('2Game_Average_Points')
Week Team 2Game_Average_Points
0 1 Team1 NaN
1 1 Team3 NaN
2 1 Team5 NaN
3 1 Team2 NaN
4 1 Team4 NaN
5 1 Team6 NaN
6 2 Team2 65.0
7 2 Team1 92.0
8 2 Team4 75.5
9 2 Team6 86.0
10 2 Team3 67.5
11 2 Team5 65.0
12 3 Team5 59.5
13 3 Team1 76.5
14 3 Team3 67.0
15 3 Team2 68.5
16 3 Team6 87.5
17 3 Team4 71.5
18 4 Team6 88.5
19 4 Team5 66.5
20 4 Team2 86.5
21 4 Team4 83.0
22 4 Team1 67.0
23 4 Team6 78.0
- группировка по командам
- выбор столбцов для усреднения (здесь
Team Points
не используетсяVs Points
, так как каждая игра появляется дважды, но вы можете добавить в список другие свои функции) - используйте функцию df.rolling() с окном 2. Число отображается только один раз, поэтому его легко изменить или использовать в качестве параметра в функции.
Как подчеркивается в другом ответе , при этом может использоваться несколько более плотная нотация groupby().rolling()
, поэтому в данном случае:
>>> roll = df.groupby('Team', as_index=False)[['Team Points']].rolling(2).mean()
Ответ №2:
NB. поскольку у вас были неоднозначные имена столбцов, я использовал Week TeamA TeamB PointsA PointsB
Я не согласен со значениями в ваших выходных данных, но если вы хотите рассчитать скользящее среднее значение по группе, вы можете сделать:
df['2Game_Average_Points'] = (df.groupby('TeamA')['PointsA']
.rolling(2).mean()
.sort_index(level=1).values
)
выход:
Week TeamA TeamB PointsA PointsB 2Game_Average_Points
0 1 Team1 Team2 94 67 NaN
1 1 Team3 Team4 51 83 NaN
2 1 Team5 Team6 74 96 NaN
3 1 Team2 Team1 67 94 NaN
4 1 Team4 Team3 83 51 NaN
5 1 Team6 Team5 96 74 NaN
6 2 Team2 Team6 63 76 65.0
7 2 Team1 Team3 90 84 92.0
8 2 Team4 Team5 68 56 75.5
9 2 Team6 Team2 76 63 86.0
10 2 Team3 Team1 84 90 67.5
11 2 Team5 Team4 56 68 65.0
12 3 Team5 Team2 63 74 59.5
13 3 Team1 Team6 63 99 76.5
14 3 Team3 Team4 50 75 67.0
15 3 Team2 Team5 74 63 68.5
16 3 Team6 Team1 99 63 87.5
17 3 Team4 Team3 75 50 71.5
18 4 Team6 Team4 78 91 88.5
19 4 Team5 Team1 70 71 66.5
20 4 Team2 Team3 99 74 86.5
21 4 Team4 Team6 91 78 83.0
22 4 Team1 Team5 71 70 67.0
23 4 Team6 Team4 78 91 78.0
Комментарии:
1. Извините, это ошибка в моих личных расчетах @mozway