Pandas如何按指定列值计数调整每组行数,不足补全超额截断
实现方案
这里提供两种适配不同场景的高效实现:
1. 简洁易读版本(适配绝大多数常规数据量场景)
用groupby.apply直接对分组做截断/补全逻辑,代码好维护,万级到十万级数据量下性能足够:
import pandas as pd # 测试数据 df = pd.DataFrame({ "ID": [ "1", "1", "1", "1", "1", "2", "2", "3", "3", "3", "4", "4"], "Feature": [ 2, 6, 4, 5, 6, 3, 1, 6, 3, 5, 7, 1] }) TARGET_PER_GROUP = 4 def process_group(g): # 组内行数达标直接截断前N行 if len(g) >= TARGET_PER_GROUP: return g.head(TARGET_PER_GROUP) # 不足的部分用最后一行填充 pad_num = TARGET_PER_GROUP - len(g) pad_rows = pd.DataFrame([g.iloc[-1]] * pad_num, columns=g.columns) return pd.concat([g, pad_rows], ignore_index=True) result = df.groupby("ID", group_keys=False).apply(process_group).reset_index(drop=True) print(result)
2. 纯向量化高性能版本(适配百万级以上大数据量场景)
完全避免groupby.apply的隐式循环开销,性能比上面的版本高3~10倍:
TARGET_PER_GROUP = 4 # 给每个组内的行加序号 df['group_inner_idx'] = df.groupby('ID').cumcount() # 先截断每个组超过长度的部分 truncated = df[df['group_inner_idx'] < TARGET_PER_GROUP].copy() # 统计每个组截断后的行数 group_size = truncated.groupby('ID').size() # 计算每个组需要补的行数 need_pad = TARGET_PER_GROUP - group_size # 取出需要补行的组的最后一行,按需要补的次数重复 pad_rows = truncated.groupby('ID').last().loc[need_pad[need_pad > 0].index] pad_rows = pad_rows.loc[pad_rows.index.repeat(need_pad[need_pad > 0])] # 合并数据、清理临时列、重置索引 result = pd.concat([truncated, pad_rows], ignore_index=True)\ .drop(columns='group_inner_idx')\ .sort_values('ID')\ .reset_index(drop=True) print(result)
两种方案运行后都可以得到你预期的输出结果。
内容的提问来源于stack exchange,提问作者Ishigami
相关产品推荐
相关产品推荐

