通过计算Pandas数据帧中的条件概率来指示偏好的新列



我有一个运动员比赛数据的巨大数据帧,看起来如下:

Race_ID  Athlete_ID  Distance  Rank
1        1           100       3
2        1           400       6
3        1           1500      1
4        1           100       6
5        1           100       1
6        1           1500      1
7        2           100       1
8        2           400       2
9        2           400       1
10       2           1500      6
11       2           1500      4
12       2           100       1
13       2           100       1

我想制作一个名为Dist_Preference的新专栏,通过计算运动员赢得该距离的条件概率来了解运动员更擅长什么距离(100(短(、400(中(、1500(长((。例如:

p(赢得100米比赛的运动员1 |这是100米比赛(=2/3

p(运动员1赢得400米比赛|这是400米比赛(=0/1=0

p(运动员1赢得1500米比赛|这是1500米比赛(=2/2=1

因此,运动员1显然具有长跑的偏好。第四个,所需的列看起来像

Race_ID  Athlete_ID  Distance  Rank  Dist_Preference
1        1           100       3     1500
2        1           400       6     1500     
3        1           1500      1     1500
4        1           100       6     1500
5        1           100       1     1500
6        1           1500      1     1500
7        2           100       1     100
8        2           400       2     100
9        2           400       1     100
10       2           1500      6     100
11       2           1500      4     100
12       2           100       1     100
13       2           100       1     100

我已经编写了一个子程序,通过定义一个方法来实现这一点,该方法如上所述计算条件概率,然后使用.apply,但对于大型数据帧来说,速度非常慢,我想知道是否有任何快速的方法可以做到这一点。

非常感谢。

创建一个布尔列:win以识别获胜的比赛,然后使用aggfuncmean透视数据帧,后者将计算概率,然后使用idxmax根据获胜概率找到首选距离

df['win'] = df['Rank'] == 1
prob = df.pivot_table('win', 'Athlete_ID', 'Distance')
df['preferred_dist'] = df['Athlete_ID'].map(prob.idxmax(1))

结果

Race_ID  Athlete_ID  Distance  Rank    win  preferred_dist
0         1           1       100     3  False            1500
1         2           1       400     6  False            1500
2         3           1      1500     1   True            1500
3         4           1       100     6  False            1500
4         5           1       100     1   True            1500
5         6           1      1500     1   True            1500
6         7           2       100     1   True             100
7         8           2       400     2  False             100
8         9           2       400     1   True             100
9        10           2      1500     6  False             100
10       11           2      1500     4  False             100
11       12           2       100     1   True             100
12       13           2       100     1   True             100

try:

df
Race_ID  Athlete_ID  Distance  Rank
1        1           100       3
2        1           400       6
3        1           1500      1
4        1           100       6
5        1           100       1
6        1           1500      1
7        2           100       1
8        2           400       2
9        2           400       1
10       2           1500      6
11       2           1500      4
12       2           100       1
13       2           100       1
df1 = df.groupby(['Athlete_ID', 'Distance']).agg(nbr_of_races=('Rank', lambda x: len(x)),
nbr_of_races_won=('Rank', lambda x: len([i for i in x if i == 1]))).reset_index()
df1['performance'] = (df1['nbr_of_races_won']*100/df1['nbr_of_races']).round(2)
df1
Athlete_ID  Distance    nbr_of_races    nbr_of_races_won    performance
0   1           100         3               1                   33.33
1   1           400         1               0                   0.00
2   1           1500        2               2                   100.00
3   2           100         3               3                   100.00
4   2           400         2               1                   50.00
5   2           1500        2               0                   0.00
#sort by performance
df1 = df1.sort_values(['Athlete_ID', 'performance'], ascending=[True, False])
Athlete_ID  Distance    nbr_of_races    nbr_of_races_won    performance
2   1           1500        2               2                   100.00
0   1           100         3               1                   33.33
1   1           400         1               0                   0.00
3   2           100         3               3                   100.00
4   2           400         2               1                   50.00
5   2           1500        2               0                   0.00
#keep only the best performed Distance for each Athlete
df1 = df1.drop_duplicates('Athlete_ID') 
Athlete_ID  Distance    nbr_of_races    nbr_of_races_won    performance
2   1           1500        2               2                   100.0
3   2           100         3               3                   100.0
#merge 
df = df.merge(df1.loc[:, ['Athlete_ID', 'Distance']].rename(columns={"Distance": "preferred_dist"}), on='Athlete_ID', how='left')
df
Race_ID Athlete_ID  Distance    Rank    preferred_dist
0   1       1           100         3       1500
1   2       1           400         6       1500
2   3       1           1500        1       1500
3   4       1           100         6       1500
4   5       1           100         1       1500
5   6       1           1500        1       1500
6   7       2           100         1       100
7   8       2           400         2       100
8   9       2           400         1       100
9   10      2           1500        6       100
10  11      2           1500        4       100
11  12      2           100         1       100
12  13      2           100         1       100

相关内容

最新更新