代码之家  ›  专栏  ›  技术社区  ›  bismo

基于python中的条件进行cumcount的更优雅的方法

  •  2
  • bismo  · 技术社区  · 4 年前

    df 由两支球队组成,他们在比赛中的得分差异。

    df = pd.DataFrame({
        'Team':['A','A','A','A','A','B','B','B','B','B'],
        'Point_Diff':[-4,5,-1,2,2,6,-5,-4,3,-1]}
        )
    df
    
    
      Team  Point_Diff
    0   A   -4
    1   A   5
    2   A   -1
    3   A   2
    4   A   2
    5   B   6
    6   B   -5
    7   B   -4
    8   B   3
    9   B   -1
    

    我想创建一个变量 Losses 这是一个累积计数,仅在 Point_Diff

    我已经能够做到这一点,尽管有点粗俗,而且有多行:

    df['Losses'] = df.loc[df.Point_Diff<0].groupby(['Team'])[['Point_Diff']].transform('cumcount')+1
    
    df.Losses = df.Losses.fillna(method='ffill')
    
    df
    
    
      Team  Point_Diff  Losses
    0   A   -4  1.0
    1   A   5   1.0
    2   A   -1  2.0
    3   A   2   2.0
    4   A   2   2.0
    5   B   6   2.0
    6   B   -5  1.0
    7   B   -4  2.0
    8   B   3   2.0
    9   B   -1  3.0
    

    必须有一种更优雅的方式来做到这一点,可能是 shift() 或者什么的,但是在把它和 groupby()

    编辑:我也注意到我的代码甚至不起作用。B队在第5行开始时出错。 损失 应该是0,而不是2。不知道为什么。

    2 回复  |  直到 4 年前
        1
  •  3
  •   richardec    4 年前

    不确定这是否是您的想法:

    df.assign(Losses=df.Point_Diff.lt(0).groupby('Team').cumsum())
    
      Team  Point_Diff  Losses
    0    A          -4       1
    1    A           5       1
    2    A          -1       2
    3    A           2       2
    4    A           2       2
    5    B           6       0
    6    B          -5       1
    7    B          -4       2
    8    B           3       2
    9    B          -1       3
    
        2
  •  2
  •   richardec    4 年前

    它可以缩短:

    df = df.assign(Losses=df[df.Point_Diff<0].groupby(['Team'])[['Point_Diff']].cumcount().add(1)).ffill()
    

    输出:

    >>> df
      Team  Point_Diff  Losses
    0    A          -4     1.0
    1    A           5     1.0
    2    A          -1     2.0
    3    A           2     2.0
    4    A           2     2.0
    5    B           6     2.0 # <-- Still 2, though.
    6    B          -5     1.0
    7    B          -4     2.0
    8    B           3     2.0
    9    B          -1     3.0