Python实现DataFrame行复制、ID列与type列生成方案
问题解决:DataFrame行复制与新增列生成
输入DataFrame
c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 56 1 2 4 1.0 1 4.0 1.0 2 2 18000.0 52 2 2 5 3.0 1 4.0 1.0 1 1 0.0 82 2 2 5 4.0 2 4.0 1.0 1 1 0.0 26 1 2 4 2.0 1 4.0 1.0 2 2 12000.0 65 1 2 4 1.0 1 4.0 23.0 2 1 324900.0
需求
- 将输入DataFrame的每一行复制3次
- 生成
id列:对应原数据的行号(从1开始),每个行号重复3次 - 生成
type列:对每条原始记录按1、2、3循环取值
期望输出
id type c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 1 1 56 1 2 4 1.0 1 4.0 1.0 2 2 18000.0 1 2 56 1 2 4 1.0 1 4.0 1.0 2 2 18000.0 1 3 56 1 2 4 1.0 1 4.0 1.0 2 2 18000.0 2 1 52 2 2 5 3.0 1 4.0 1.0 1 1 0.0 2 2 52 2 2 5 3.0 1 4.0 1.0 1 1 0.0 2 3 52 2 2 5 3.0 1 4.0 1.0 1 1 0.0 3 1 82 2 2 5 4.0 2 4.0 1.0 1 1 0.0 3 2 82 2 2 5 4.0 2 4.0 1.0 1 1 0.0 3 3 82 2 2 5 4.0 2 4.0 1.0 1 1 0.0 4 1 26 1 2 4 2.0 1 4.0 1.0 2 2 12000.0 4 2 26 1 2 4 2.0 1 4.0 1.0 2 2 12000.0 4 3 26 1 2 4 2.0 1 4.0 1.0 2 2 12000.0 5 1 65 1 2 4 1.0 1 4.0 23.0 2 1 324900.0 5 2 65 1 2 4 1.0 1 4.0 23.0 2 1 324900.0 5 3 65 1 2 4 1.0 1 4.0 23.0 2 1 324900.0
你的尝试代码(存在问题)
(df .dropna() .assign(id = lambda x: range(1, len(x) + 1) ) .pipe(lambda x: x.loc[x.index.repeat(3)]) .assign(id = lambda x: np.r_[:len(x)] % 3 + 1, type = lambda x: np.r_[:len(x)] % 3 + 1))
问题分析:第二次assign覆盖了初始正确的id值,用np.r_[:len(x)] %3 +1生成的是1、2、3循环序列,而非原行号重复3次的结果。
正确实现方法
方法一:保留初始id,新增type列
先给原DataFrame添加从1开始的行号作为id,再重复行、生成type列:
import pandas as pd import numpy as np result = (df .dropna() .assign(id=lambda x: range(1, len(x)+1)) # 生成原行号id .loc[lambda x: x.index.repeat(3)] # 每行重复3次 .assign(type=lambda x: np.tile([1,2,3], len(x)//3)) # 循环生成type值 .reset_index(drop=True))
方法二:重复后计算id
无需提前添加id,通过重复后的索引位置反推原行号:
result = (df .dropna() .loc[lambda x: x.index.repeat(3)] .assign(id=lambda x: (x.index // 3) + 1, # 从重复后的索引计算原行号 type=lambda x: np.tile([1,2,3], len(df))))
方法三:用explode简化逻辑
给每行添加包含[1,2,3]的type列表,再展开列表生成多行:
result = (df .dropna() .assign(id=range(1, len(df)+1), type=[[1,2,3]]*len(df)) .explode('type') .reset_index(drop=True))
以上三种方法均可得到符合要求的输出,其中方法三逻辑更直观,代码更简洁。
内容的提问来源于stack exchange,提问作者Eisen
相关产品推荐
相关产品推荐

