如何在Pandas中按组循环重复行模式n次并生成日序列?
高效实现按组循环分配组合到连续n天
问题背景
给定如下Pandas DataFrame:
import pandas as pd df = [[1, 'a1 - d1'], [1, 'b1 - c1'], [1, 'd1 - c1'], [1, 'a1 - b1'], [1, 'b1 - d1'], [1, 'c1 - a1'], [2, 'y1 - z1'], [2, 'x1 - y1'], [2, 'z1 - x1']] df = pd.DataFrame(df, columns=['group_id', 'combinations'])
对应的表格结构:
| group_id | combinations |
|---|---|
| 1 | a1 - d1 |
| 1 | b1 - c1 |
| 1 | d1 - c1 |
| 1 | a1 - b1 |
| 1 | b1 - d1 |
| 1 | c1 - a1 |
| 2 | y1 - z1 |
| 2 | x1 - y1 |
| 2 | z1 - x1 |
需求:
- 连续
n天(示例n=30),每天为每个group_id分配一个组合 - 组合按组内原有顺序循环使用,无论组内组合数多于或少于
n - 最终生成包含天数、
group_id、对应组合的结果表
原实现采用分组循环拼接的方式,效率较低,寻求更高效的替代方案。
高效实现方法
方法一:利用groupby + repeat + head
通过Pandas分组后的矢量化操作,避免显式循环:
n = 30 # 分组处理:计算每个组的重复次数,重复后截取前n行 result = (df.groupby('group_id', group_keys=False) .apply(lambda g: g.loc[g.index.repeat((n + len(g) - 1) // len(g))].head(n))) # 为每个组添加连续天数编号 result['day'] = result.groupby('group_id').cumcount() + 1 # 调整列顺序并重置索引 result = result[['day', 'group_id', 'combinations']].reset_index(drop=True)
方法二:基于numpy.tile生成索引(性能更优)
利用numpy的tile函数生成重复索引,直接提取目标行,性能优于apply操作:
import numpy as np n = 30 # 按group_id分组,存储每个组的行索引和长度 groups = df.groupby('group_id') group_indices = {g: idx.values for g, idx in groups.groups.items()} group_sizes = {g: len(idx) for g, idx in groups.groups.items()} # 生成每个组需要的重复索引,截取前n个 all_indices = [] for g in group_indices: repeats = (n + group_sizes[g] - 1) // group_sizes[g] indices = np.tile(group_indices[g], repeats)[:n] all_indices.extend(indices) # 提取目标行并添加天数列 result = df.loc[all_indices].copy() result['day'] = np.repeat(np.arange(1, n+1), len(group_indices)) # 调整列顺序并重置索引 result = result[['day', 'group_id', 'combinations']].reset_index(drop=True)
核心逻辑说明
- 两种方法均避免了显式循环,利用Pandas/numpy的矢量化操作提升效率,数据量越大优势越明显
- 通过
(n + 组大小 - 1) // 组大小计算每个组的重复次数,等价于向上取整ceil(n/组大小),确保能覆盖n天的需求后再截取前n行 - 天数列通过
cumcount或np.repeat生成,保证每个组内天数从1到n连续编号
内容的提问来源于stack exchange,提问作者n3a5p7s9t1e3r
相关产品推荐
相关产品推荐

