【问题标题】:Calculate sum of row based on condition根据条件计算行总和
【发布时间】:2024-05-21 10:55:01
【问题描述】:

我有一个 df

data = [[1, 10], [1, 5], [1, 4], [0, 3], [0, 3], [1, 2], [1, 1], [1, 5], [2, 8], [4, 9]]
df = pd.DataFrame(data, columns = ['no', 'count'])

将值打印为,

no  count
1    10   
1    5
1    4
0    3
0    3
1    2
1    1
1    5
2    8
4    9 
  • 我想在“否”变为 1 时获得第一个“计数”(考虑为值 1)
  • 当数字为“非 1”时,获取该“计数”(考虑为值 2)
  • 减去 value2 - value1
  • 当“no”再次变为 1 时开始下一个值。
  • 最后,计算总和

预期输出: (10-3) = 7 和 (2-8) = -6

7
-6

总和是,

1

【问题讨论】:

    标签: python python-3.x pandas python-2.7


    【解决方案1】:

    groupby df['no'].eq(1) (m) 和 m.ne(m.shift()).cumsum() 的另一种方法:

    m = df['no'].eq(1)
    g = (
        df.groupby([m, m.ne(m.shift()).cumsum()])['count'].first()
    )
    
    no     no
    False  2      3
           4      8
    True   1     10
           3      2
    Name: count, dtype: int64
    

    然后从False no 中减去True no:

    g.loc[True].values - g.loc[False].values
    
    [ 7 -6]
    

    sum:

    (g.loc[True].values - g.loc[False].values).sum()
    
    1
    

    【讨论】:

    • 更新为掩码,其中 m 是 1 而不是直接 @sam 的 'no`
    【解决方案2】:

    这是一种方法:

    >>> vals = df.groupby(df.no.eq(1).diff().ne(0).cumsum())["count"].first()
    >>> result = (vals * (-1) ** np.arange(len(vals))).sum()
    >>> result
    1
    

    我们首先对连续的组进行分组,它们是否为 1 并取其中的第一个值。然后为这些值加上一个交替符号,我们使用(-1)0..N-1 的幂。然后我们将乘法相加。

    vals是这个:

    1    10
    2     3
    3     2
    4     8
    

    不乘以 -1 次方的替代方案:

    vals = df.groupby(df.no.eq(1).diff().ne(0).cumsum())["count"].first().to_numpy()
    
    result = (vals[::2] - vals[1::2]).sum()
    

    我们从偶数索引值中减去奇数索引值。


    基于itertools.groupby 的另一种替代方案,带有 1 次数据传递:

    from itertools import groupby
    from operator import itemgetter
    
    iterable = enumerate(groupby(zip(df["no"].eq(1), df["count"]), key=itemgetter(0)))
    
    result = sum((1-2*(j&1)) * next(gr)[1] for j, (_, gr) in iterable)
    

    它通过枚举和j 的奇偶校验即时确定符号。但不那么可读。

    【讨论】:

    • 稍微更新了问题,请检查一下
    • @sam 编辑了答案,groupby 改了一点(其实简化了)。希望对您有所帮助。