
本文介绍一种高效、可复用的方法:根据“country type”列是否为none,自动在每条“origin”记录下方插入或更新一行,统一填充“citizenship”和“uk”,同时保持原始行顺序与结构完整性。
本文介绍一种高效、可复用的方法:根据“country type”列是否为none,自动在每条“origin”记录下方插入或更新一行,统一填充“citizenship”和“uk”,同时保持原始行顺序与结构完整性。
在实际数据清洗与ETL任务中,常需基于业务逻辑动态扩展DataFrame——例如为每个具有明确“Origin”的人员补充对应的“Citizenship”信息行。Pandas本身不支持原地“在某行后插入”,但可通过布尔索引、条件筛选与pd.concat()组合实现语义等价的操作。
核心思路分三步:
- 识别目标行:找出所有 Country Type == "Origin"(即非空且值为Origin)的原始记录;
- 区分处理策略:若其下一行已存在且 Country Type 为 None(如示例中第2行后的隐含空行),则直接填充该行;否则需新增一行;
- 构造并合并:分别构建三类数据块——保留的原始行、需填充的现有空行、以及新增的空行,并按原始索引稳定排序拼接。
以下是完整可运行代码:
import pandas as pd
# 构造原始数据
data = {
'Name_Type': ["Primary", "Primary", "AKA", "Primary"],
'Name': ["John", "Daniel", "Dan", "Bob"],
'Surname': ["Green", "Brown", "Brown", "White"],
'Country Type': ["Origin", "Origin", None, "Origin"],
'Country': ["UK", "UK", None, "UK"],
'Other': ["Info", None, None, "Info"]
}
df = pd.DataFrame(data)
# 步骤1:构建布尔掩码
m = df['Country Type'].isna() # 标记当前行为None的行(如第2行)
m2 = ~(m | m.shift(-1)) # 标记"Origin"行:既不是None,且下一行也不是None(即需新增行)
# 步骤2:定义填充值
fill = {'Country Type': 'Citizenship', 'Country': 'UK'}
# 步骤3:拼接三部分
out = pd.concat([
df[m2], # 原始的Origin行(保留)
df.loc[m2, ['Country']].assign(**fill), # 新增行:仅Country列参与,其余置NaN
df[~m2].fillna(fill) # 已存在的None行(如第2行):用fill填充对应列
]).sort_index(kind='stable').reset_index(drop=True) # 稳定排序 + 重置索引(可选)
print(out)✅ 输出结果:
Name_Type Name Surname Country Type Country Other 0 Primary John Green Origin UK Info 1 NaN NaN NaN Citizenship UK NaN 2 Primary Daniel Brown Origin UK None 3 AKA Daniel Brown Citizenship UK None 4 Primary Bob White Origin UK Info 5 NaN NaN NaN Citizenship UK NaN
⚠️ 注意事项:
- m.shift(-1) 用于检测“下一行是否为空”,确保不重复处理已存在的空行;
- sort_index(kind='stable') 是关键——避免相同索引导致的随机排序,保证插入位置准确;
- reset_index(drop=True) 可选,用于获得连续整数索引(生产环境建议保留原始索引便于溯源);
- 若需填充多列(如同时设Other="Citizenship Record"),只需扩展 fill 字典即可;
- 此方法时间复杂度为 O(n),适用于万级以内数据;超大规模时建议改用numpy向量化预分配+iloc赋值优化性能。
该方案兼顾可读性与健壮性,无需循环,完全向量化,是Pandas中处理“条件性行插入”任务的推荐实践。

















