
本文介绍如何基于“country type”列是否为none的条件,在每条“origin”记录下方智能插入或更新一行,统一填入“citizenship”和“uk”,并保持原始行序与结构完整性。
本文介绍如何基于“country type”列是否为none的条件,在每条“origin”记录下方智能插入或更新一行,统一填入“citizenship”和“uk”,并保持原始行序与结构完整性。
在数据清洗与报表生成场景中,常需根据现有逻辑动态扩展DataFrame结构——例如为每个具有明确“Origin”的人员补充其“Citizenship”信息行。关键挑战在于:既要避免重复插入(如已有空行则复用),又要确保新行严格位于目标行正下方,且索引有序、字段对齐。
以下为完整实现方案,采用布尔掩码+分块拼接策略,兼顾可读性与性能:
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:识别需处理的“Origin”行(即 Country Type == 'Origin' 且下一行非空行)
m = df['Country Type'].isna() # 标记原为空的行(如第2行)
m2 = ~(m | m.shift(-1)) # 掩码m2为True → 当前行是Origin,且下一行不是已存在的空行(即需新建)
# 步骤2:定义填充内容
fill_values = {'Country Type': 'Citizenship', 'Country': 'UK'}
# 步骤3:三路拼接
out = pd.concat([
df[m2], # 原始的Origin行(保留)
df.loc[m2, ['Country']].assign(**fill_values), # 新增行:仅复制Country列再填充Type/Country
df[~m2].fillna(fill_values) # 复用已存在空行:用fill_values填充对应列
], ignore_index=False).sort_index(kind='stable') # stable保证相同索引的行顺序不变
print(out)输出结果:
Name_Type Name Surname Country Type Country Other 0 Primary John Green Origin UK Info 0 NaN NaN NaN Citizenship UK NaN 1 Primary Daniel Brown Origin UK None 2 AKA Dan Brown Citizenship UK None 3 Primary Bob White Origin UK Info 3 NaN NaN NaN Citizenship UK NaN
✅ 关键说明:
- m2 是核心逻辑:它精准定位所有需要“触发插入”的 Origin 行(即该行下紧邻无空行);
- df.loc[m2, ['Country']].assign(...) 构造新行时仅继承必要列(如Country),其余自动设为NaN,符合“新增行”的语义;
- df[~m2].fillna(...) 则负责复用已存在的空行(如原第2行),仅填充目标字段,保留其他列(如Name_Type仍为AKA);
- sort_index(kind='stable') 确保多段concat后索引有序且相同索引的行不乱序(尤其重要,因concat默认重排);
- 最终结果中,Name、Surname等非填充列在新增行中自然为NaN,符合预期;若需继承上一行姓名,可额外添加 .assign(Name=df.loc[m2, 'Name'].values, Surname=df.loc[m2, 'Surname'].values)。
? 注意事项:
- 本方案假设“Origin”行与后续空行成对出现,且空行唯一标识为Country Type和Country均为None;
- 若数据含多重嵌套逻辑(如多个空行、混合类型),建议先用df.groupby(...)预分组再逐块处理;
- 生产环境建议封装为函数,并加入inplace=False与copy()防护,避免意外修改原始DataFrame。

















