You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对DataFrame分组后统计每组连续1的最大数量并映射至全行

解决按组统计连续1的最大次数并映射到每行的问题

这是个很典型的连续序列统计需求,我来一步步带你实现:

首先,先确认输入数据:

import pandas as pd

df = pd.DataFrame({
    'A':[1,1,1,1,1,1,2,2,2,2,2,2,2],
    'flag':[1,1,0,1,1,1,0,1,1,0,1,1,1]
})

步骤1:识别每组内的连续1区块

我们需要在每个A分组内,给连续的1(以及单独的0)分配唯一的区块ID,这样才能统计每个区块的长度:

df['block_id'] = df.groupby('A')['flag'].apply(
    lambda x: (x != x.shift() | (x == 0)).cumsum()
)

这里的逻辑是:

  • x != x.shift()标记每个连续序列的起始位置(比如从0变1,或者从1变0)
  • | (x == 0)把所有0的位置也单独划成一个区块,避免和后面的1区块混淆
  • cumsum()给每个连续区块分配递增的ID

步骤2:计算每个1区块的长度并取组内最大值

接下来筛选出所有flag=1的区块,统计每个区块的长度,再按A分组取最大值:

# 统计每个1区块的长度
block_lengths = df[df['flag'] == 1].groupby(['A', 'block_id']).size()
# 按A分组取最大的连续1长度
max_consec = block_lengths.groupby('A').max().rename('consective_count_max')

步骤3:将最大值映射回原DataFrame的每一行

最后把计算好的最大值合并回原数据,每个A组的所有行都会得到对应的最大值:

output = df[['A']].merge(max_consec, on='A', how='left')

更简洁的写法(用transform一步到位)

如果想简化代码,可以用groupby.transform直接把组内最大值应用到每一行:

def get_max_consec_ones(series):
    # 生成区块ID
    blocks = (series != series.shift() | (series == 0)).cumsum()
    # 计算每个区块长度,筛选出1的区块后取最大值
    block_sizes = series.groupby(blocks).size()
    # 只保留flag为1的区块的长度,再取最大
    return block_sizes[series.groupby(blocks).first() == 1].max()

# 直接用transform把结果映射到每行
output = df.assign(
    consective_count_max=df.groupby('A')['flag'].transform(get_max_consec_ones)
)[['A', 'consective_count_max']]

运行后得到的output就是你期望的结果:

A  consective_count_max
0   1                     3
1   1                     3
2   1                     3
3   1                     3
4   1                     3
5   1                     3
6   2                     3
7   2                     3
8   2                     3
9   2                     3
10  2                     3
11  2                     3
12  2                     3

内容的提问来源于stack exchange,提问作者Nickel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 07:52:52