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

如何将Pandas DataFrame复制N次并分配新ID,保留原关联数据

问题描述

给定如下DataFrame:

import pandas as pd
df = pd.DataFrame({'id':[1,3,500, 53, 1, 500], 
                   'code1':['a0', 'b0', 'b0', 'c0', 'b0', 'a0'], 
                   'code2':['aa', 'bb', 'cc', 'bb', 'cc', 'bb'], 
                   'date':['2022-10-01', '2022-09-01', '2022-10-01', '2022-11-01', '2022-09-01', '2022-11-01']})

需要将该DataFrame复制N次,每次副本需分配全新的ID,同时保留原ID对应的code1/code2/date组合关系(即原ID=1对应的所有行组合,新ID也要完全复用这些组合)。

当N=1时,可通过以下代码实现:

df1 = df.loc[df.index.repeat(1)]  # 等效于直接复制

ids = df.id.unique() # 获取原始唯一ID
new_ids_start = df.id.max() + 1  # 新ID从原最大ID+1开始
nids = df.id.nunique() # 原始唯一ID的数量
new_ids = new_ids_start + range(0, nids) # 生成新ID列表

df1['id'] = df1['id'].replace(ids, new_ids) # 替换旧ID为新ID

df_final = pd.concat([df, df1], axis=0)  # 合并原数据和副本

但对于N≥2的场景,原本考虑用循环实现,想知道是否有更高效的非循环方案?核心要求是保留每个ID对应的组合关系,同时保留原ID数据。

解决方案

可以通过批量生成ID映射表 + 向量化操作实现,完全避免循环,效率更高,尤其适合数据量或N较大的场景:

向量化实现方案(推荐)

import pandas as pd
import numpy as np

# 原始数据
df = pd.DataFrame({'id':[1,3,500, 53, 1, 500], 
                   'code1':['a0', 'b0', 'b0', 'c0', 'b0', 'a0'], 
                   'code2':['aa', 'bb', 'cc', 'bb', 'cc', 'bb'], 
                   'date':['2022-10-01', '2022-09-01', '2022-10-01', '2022-11-01', '2022-09-01', '2022-11-01']})

N = 2  # 设定需要复制的次数

# 1. 提取原始唯一ID及其索引映射
original_ids = df.id.unique()
id_index_map = {id_val: idx for idx, id_val in enumerate(original_ids)}
n_unique_ids = len(original_ids)
max_original_id = df.id.max()

# 2. 生成所有副本的ID偏移量:每轮副本的ID偏移为 轮次序号 * 唯一ID数量
offsets = np.arange(1, N+1) * n_unique_ids
# 3. 为每个原始ID生成对应N轮副本的新ID
# 公式:新ID = 原最大ID + 偏移量 + 原始ID的索引(保证组合关系不变)
new_ids_matrix = max_original_id + offsets + np.arange(n_unique_ids)[:, None]

# 4. 构建完整的ID映射字典:原始ID → [第1轮新ID, 第2轮新ID, ..., 第N轮新ID]
full_id_map = {original_ids[i]: new_ids_matrix[i] for i in range(n_unique_ids)}

# 5. 生成所有副本并替换ID
# 重复原始数据N次,得到副本数据集
df_repeats = df.loc[df.index.repeat(N)].reset_index(drop=True)
# 按原始ID分组,将每组的ID替换为对应的N轮新ID序列
df_repeats['id'] = df_repeats.groupby('id')['id'].transform(
    lambda x: np.tile(full_id_map[x.iloc[0]], len(x) // N)
)

# 6. 合并原数据与所有副本,得到最终结果
df_final = pd.concat([df, df_repeats], axis=0).reset_index(drop=True)

方案说明

  • 核心逻辑是保留原始ID与组合的对应关系:每个原始ID的索引固定,每轮副本的新ID基于原最大ID + 轮次偏移 + 原始ID索引生成,确保同一原始ID的所有组合在副本中对应同一个新ID。
  • 全程使用numpy向量化操作和pandas分组变换,避免了循环带来的性能损耗,处理大规模数据时优势明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 05:25:52