Python Pandas已分组对象能否再次分组?分组内按文件号序列移位问题
对Pandas分组对象再次应用groupby的解决方案
当然可以对Pandas的已分组对象再次嵌套使用groupby——这正是处理这类“分组内再细分场景”的标准方式。你的问题核心在于当前的连续序列标识diff是基于整个数据集计算的,没有考虑Date和Batch的分组边界,导致跨分组的连续File_no被错误合并,最终移位结果不符合预期。
问题拆解
你需要的逻辑是:
- 先按
Date和Batch对数据进行一级分组 - 在每个一级分组内部,再按连续的
File_no序列进行二级分组 - 仅在每个二级连续分组内,对
A、B列执行移位操作(即只有连续的File_no行才会继承前一行的A、B值,非连续行的移位结果为NaN)
解决方案代码
首先还原你的测试数据集:
import pandas as pd data = pd.DataFrame({ 'File_no': [1,2,3,5,6,8], 'A': [2,7,9,6,4,2], 'B': [3,6,2,3,3,3], 'Date': ['23-1-2019','23-1-2019','24-1-2019','24-1-2019','24-1-2019','25-1-2019'], 'Batch': [2,2,1,2,1,1], 'State': [3,4,2,3,4,4] })
然后编写分组处理函数,实现嵌套分组移位:
def process_group(group): # 1. 确保组内按File_no排序(避免原数据乱序影响结果) group = group.sort_values('File_no').reset_index(drop=True) # 2. 在当前(Date,Batch)分组内,计算连续File_no的分组标识 # 当当前File_no与前一个的差≠1时,标记为新的连续组 group['contiguous_group'] = group['File_no'].diff().ne(1).cumsum() # 3. 按连续组嵌套分组,对A、B列执行移位 shifted_cols = group.groupby('contiguous_group')[['A', 'B']].shift() # 4. 将移位结果合并回原分组,清理临时列 group[['A', 'B']] = shifted_cols return group.drop(columns='contiguous_group') # 执行一级分组+嵌套处理 result = data.groupby(['Date', 'Batch'], group_keys=False).apply(process_group)
输出结果
运行上述代码后,输出与你的预期完全一致:
File_no A B Date Batch State 0 1 NaN NaN 23-1-2019 2 3 1 2 2.0 3.0 23-1-2019 2 4 2 3 NaN NaN 24-1-2019 1 2 3 5 NaN NaN 24-1-2019 2 3 4 6 NaN NaN 24-1-2019 1 4 5 8 NaN NaN 25-1-2019 1 4
为什么你的原代码不行?
你的原代码中,diff = data['File_no'].diff().ne(1).cumsum()是全局计算的连续分组标识,比如File_no=5和File_no=6是连续的,会被归为同一个diff组,但它们属于不同的Batch,导致你的嵌套分组会跨(Date,Batch)边界处理移位,最终得到错误结果。而我们的方案把连续组的计算限制在每个(Date,Batch)分组内部,完美解决了这个问题。
内容的提问来源于stack exchange,提问作者hakuna_code
相关产品推荐
相关产品推荐

