代码之家  ›  专栏  ›  技术社区  ›  Nayr borcherds

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

  •  1
  • Nayr borcherds  · 技术社区  · 4 年前

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

    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 但对于大型数据帧来说,速度非常慢,我想知道是否有什么快速的方法可以做到这一点。

    非常感谢。

    1 回复  |  直到 4 年前
        1
  •  1
  •   Shubham Sharma mkln    4 年前

    创建布尔列: win 要确定获胜的比赛,请使用aggfunc透视数据帧 mean 它将计算概率,然后使用 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
    
        2
  •  1
  •   khaled koubaa    4 年前

    尝试:

    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