【问题标题】:Pandas: Cumulative sum within group with two conditions熊猫:有两个条件的组内累计和
【发布时间】:2021-08-09 08:21:38
【问题描述】:

我有一个如下表所示的 DataFrame:

index x y value_1 cumsum_1 cumsum_2
0 0.1 1 12 12 0
1 1.2 1 10 12 10
2 0.25 1 7 19 10
3 1.0 2 3 0 3
4 0.72 2 5 5 10
5 1.5 2 10 5 13

所以我的目标是计算value_1 的累积和。但有两个条件必须考虑。

  • 首先:如果值x 小于1,则cumsum() 写入列cumsum_1,如果x 大于列cumsum_2
  • 第二个:y 列表示组 (1,2,3,...)。当y 中的值发生变化时,cumsum() 操作会重新开始。我认为grouby() 方法会有所帮助。

有人知道吗?

【问题讨论】:

  • 你能显示预期的输出以使其更清晰吗?
  • 期望输出显示在cumsum_1cumsum_2列中。
  • 提示:(1) df['x'] < 1 为您提供一列布尔值,(2) 将此列乘以 df['value_1'] 会得到 df['x'] 小于 1 的值,而在其他地方则为 0 , (3) 取本列的cumsum, (4) 对不小于1的值重复。这样就解决了第一部分。

标签: python pandas cumsum


【解决方案1】:

可以在x x >= 1的条件下使用.where(),根据条件临时修改value_1的值为0,然后groupby cumsum,如下:

.groupby 函数满足第二个条件,.where() 函数满足第一个条件,详情如下:

.where() 在条件为真时保留列值,并在条件为假时更改值(在本例中为 0)。因此,对于列x value_1 将保留其值以提供给后续cumsum 步骤以累积value_1 的过滤值。对于条件 x value_1 的值被屏蔽为 0。这些 0 传递给 cumsum 进行累加实际上与取出 value_1 的原始值进行累加的效果相同进入 专栏cumsum_1

第二行代码将value_1 的值累加到cumsum_2 列,而x >= 1 的相反条件。这两行代码实际上将value_1 分配给cumsum_1 和@987654345 @ 根据x x >= 1,分别。

(感谢@tdy 建议简化代码)

df['cumsum_1'] = df['value_1'].where(df['x'] < 1, 0).groupby(df['y']).cumsum()
df['cumsum_2'] = df['value_1'].where(df['x'] >= 1, 0).groupby(df['y']).cumsum()

结果:

print(df)

      x  y  value_1  cumsum_1  cumsum_2
0  0.10  1       12        12         0
1  1.20  1       10        12        10
2  0.25  1        7        19        10
3  1.00  2        3         0         3
4  0.72  2        5         5         3
5  1.50  2       10         5        13

【讨论】:

  • +1,但可以通过Series.where避开中间列,例如df['cumsum_1'] = df.value_1.where(df.x &lt; 1, 0).groupby(df.y).cumsum()
  • @tdy 哦,是的!谢谢你的建议。 :-)
【解决方案2】:

这是另一种使用枢轴的方法:

(df.assign(ge1=df['x'].ge(1).map({True: 'cumsum_2', False: 'cumsum_1'}))
   .pivot(columns='ge1', values='value_1').fillna(0).groupby(df['y']).cumsum()
   .astype(int)
)

输出:

ge1  cumsum_1  cumsum_2
0          12         0
1          12        10
2          19        10
3           0         3
4           5         3
5           5        13

完整代码:

df[['cumsum_1', 'cumsum_2']] = (df.assign(ge1=df['x'].ge(1).map({True: 'cumsum_2', False: 'cumsum_1'}))
                                  .pivot(columns='ge1', values='value_1').fillna(0).groupby(df['y']).cumsum()
                                  .astype(int)
                                )

(或使用pd.concat 连接)

输出:

   index     x  y  value_1  cumsum_1  cumsum_2
0      0  0.10  1       12        12         0
1      1  1.20  1       10        12        10
2      2  0.25  1        7        19        10
3      3  1.00  2        3         0         3
4      4  0.72  2        5         5         3
5      5  1.50  2       10         5        13

【讨论】:

    【解决方案3】:

    与上述方法类似,但更具有链接性。

    df[['cumsum_1a', 'cumsum2a']] = (df.
     assign(
        v1 = lambda temp: temp.x >= 1,
        v2 = lambda temp: temp.v1 * temp.value_1,
        v3 = lambda temp: ~ temp.v1 * temp.value_1
        ).
     groupby('y')[['v2', 'v3']].
     cumsum()
     )
    

    【讨论】:

      猜你喜欢
      • 2018-10-30
      • 2019-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-21
      • 1970-01-01
      相关资源
      最近更新 更多