#python #pandas
Вопрос:
У меня есть таблица (пример ниже)
kick_result kick_yards kicker
50 MADE 28.0 X1
64 MADE 30.0 X2
75 MADE 27.0 X2
158 MADE 32.0 X2
259 MISS 46.0 X3
Для каждого значения кикера —
Я хочу подсчитать, сколько полевых целей было сделано и пропущено (в %)
Для каждого значения кикера —
Я хочу найти количество забитых и пропущенных полевых мячей на каждом расстоянии ярдов
Ответ №1:
По вашему требованию состоит из 2 частей:
- цели на местах %, и
- полевые цели во дворах,
давайте решим это один за другим.
Часть 1. Цели на местах %
Мы можем использовать df.groupby()
вместе с .value_counts(normalize=True)
, чтобы получить его:
(df.groupby('kicker')['kick_result']
.value_counts(normalize=True).mul(100).round(2)
.sort_index()
.to_frame(name='Result_%')
).reset_index()
Тестовый запуск
Построение Тестовых Данных:
Чтобы провести полное тестирование различных требований, я добавил тестовые данные следующим образом:
kick_result kick_yards kicker
49 MADE 18.0 X1
50 MADE 28.0 X1
51 MADE 38.0 X1
52 MISS 48.0 X1
53 MISS 58.0 X1
64 MADE 30.0 X2
75 MADE 27.0 X2
158 MADE 32.0 X2
159 MISS 32.0 X2
160 MISS 42.0 X2
259 MISS 46.0 X3
260 MISS 26.0 X3
261 MADE 56.0 X3
Запустите код:
(df.groupby('kicker')['kick_result']
.value_counts(normalize=True).mul(100).round(2)
.sort_index()
.to_frame(name='Result_%')
).reset_index()
Результат:
kicker kick_result Result_%
0 X1 MADE 60.00
1 X1 MISS 40.00
2 X2 MADE 60.00
3 X2 MISS 40.00
4 X3 MADE 33.33
5 X3 MISS 66.67
Часть 2: Полевые цели во дворах
Мы можем использовать pd.crosstab()
вместе с pd.cut()
для построения таблицы с диапазонами ярдов.
Также включено общее количество попыток для всех диапазонов.
pd.crosstab(index=[df['kicker'], pd.cut(df['kick_yards'],[0, 20, 30, 40, 50, np.inf])],
columns=df['kick_result'],
margins=True, margins_name='Total_Attempts')
Результат (с использованием обогащенных тестовых данных):
kick_result MADE MISS Total_Attempts
kicker kick_yards
X1 (0.0, 20.0] 1 0 1
(20.0, 30.0] 1 0 1
(30.0, 40.0] 1 0 1
(40.0, 50.0] 0 1 1
(50.0, inf] 0 1 1
X2 (20.0, 30.0] 2 0 2
(30.0, 40.0] 1 1 2
(40.0, 50.0] 0 1 1
X3 (20.0, 30.0] 0 1 1
(40.0, 50.0] 0 1 1
(50.0, inf] 1 0 1
Total_Attempts 7 6 13
Ответ №2:
Давайте свяжемся цепью с cut
и crosstab
out = pd.crosstab([df.kicker,pd.cut(df.kick_yards,[20,30,40,50,np.Inf],include_lowest=True)]
,df.kick_result,normalize='index')
out
Out[228]:
kick_result MADE MISS
kicker kick_yards
X1 (19.999, 30.0] 1.0 0.0
X2 (19.999, 30.0] 1.0 0.0
(30.0, 40.0] 1.0 0.0
X3 (40.0, 50.0] 0.0 1.0
Комментарии:
1. Это работает, но мне это нужно для каждого значения кикера — так что это даст мне только итоги.
2. есть ли также способ добавить общее количество попыток в этот кадр?
3. @Gamecocks20 проверьте поля в перекрестной таблице pandas.pydata.org/docs/reference/api/pandas.crosstab.html
4. @BENY Не должен ли X2 иметь 3, а не 2?
5. @BENY — Я ищу, но продолжаю получать ошибки при попытке реализовать поля. Я просто хочу добавить соответствующее количество (попыток) для каждой категории в группе
Ответ №3:
Используйте рычаги get_dummies
cut
и создайте результирующую DataFrame
:
df['Att'] = 1
dfmm = pd.get_dummies(df['kick_result'])
cols_A = ['A20','A21-30','A31-40','A41-50','A51 ']
cols_M = [x.replace('A','M') for x in cols_A]
df_att = pd.DataFrame(pd.get_dummies(pd.cut(df.kick_yards,[0,20,30,40,50,np.Inf],include_lowest=True)))
df_att.columns = df_att.columns.to_list()
df_att.columns = cols_A
df_made = df_att.multiply(dfmm['MADE'], axis=0)
df_made.columns=cols_M
dff = pd.concat([df,dfmm,df_att,df_made], axis=1).drop(['kick_result','kick_yards'], axis=1)
Результирующий кадр данных:
kicker Att MADE MISS A20 A21-30 A31-40 A41-50 A51 M20 M21-30
0 X1 1 1 0 0 1 0 0 0 0 1
1 X2 1 1 0 0 1 0 0 0 0 1
2 X2 1 1 0 0 1 0 0 0 0 1
3 X2 1 1 0 0 0 1 0 0 0 0
4 X3 1 0 1 0 0 0 1 0 0 0
M31-40 M41-50 M51
0 0 0 0
1 0 0 0
2 0 0 0
3 1 0 0
4 0 0 0
Агрегация из этого фрейма данных:
dff.groupby('kicker').agg(['sum'])
Att MADE MISS A20 A21-30 A31-40 A41-50 A51 M20 M21-30 M31-40 M41-50
sum sum sum sum sum sum sum sum sum sum sum sum
kicker
X1 1 1 0 0 1 0 0 0 0 1 0 0
X2 3 3 0 0 2 1 0 0 0 2 1 0
X3 1 0 1 0 0 0 1 0 0 0 0 0
M51
sum
kicker
X1 0
X2 0
X3 0