如何原地覆写pandas DataFrame列实现地址字段空缺补全
pandas地址列左移补全清洗方案
你之前的代码存在几个基础语法和逻辑错误,是导致结果异常的核心原因:
- pandas选取多列必须使用双层方括号,写
df_raw_data['ID', 'add_1', 'add_2']会被识别为查找键为元组的单列,无法选中目标三列 - pandas判断空值不能用
is None,该语法仅能识别Python原生None对象,无法识别pandas的NaN、空字符串、全空格字符串这类空值,需要用isna()方法配合空值替换逻辑 - 代码中
df_raw_data['add_']为笔误的不存在列名,会直接触发报错 np.where返回的是一维数组,直接给多列赋值会丢失列结构,自然无法保留原有非空行的值、原索引和其他非地址列
不需要新建DataFrame做合并,直接在原DataFrame上操作即可保留所有原有结构,具体实现步骤如下:
1. 预处理统一空值格式
先把地址列中的空字符串、全空格内容统一转换为pandas可识别的NaN,避免空值判断遗漏:
import pandas as pd import numpy as np # 指定要处理的三个地址列,其余列不受任何影响 addr_columns = ['add_1', 'add_2', 'add_3'] # 替换所有空串、全空格值为NaN df_raw_data[addr_columns] = df_raw_data[addr_columns].replace(r'^\s*$', np.nan, regex=True)
2. 执行左移补全逻辑
用行级排序把非空值全部靠左对齐,空值自动挤到最右侧,逻辑完全匹配你的需求,不会改动原有非空值:
df_raw_data[addr_columns] = pd.DataFrame( df_raw_data[addr_columns].values.tolist() ).apply(lambda x: sorted(x, key=pd.isna), axis=1, raw=True).values
如果你希望逻辑更透明、方便后续调整,也可以用分步填充的写法,效果完全一致:
# 优先填充最左侧add_1:自身为空时依次取add_2、add_3的值 df_raw_data['add_1'] = df_raw_data['add_1'].fillna(df_raw_data['add_2']).fillna(df_raw_data['add_3']) # 填充add_2:自身为空且add_3的值没被用来填add_1时,把add_3的值移到add_2 fill_ad2_mask = df_raw_data['add_2'].isna() & (df_raw_data['add_1'] != df_raw_data['add_3']) df_raw_data.loc[fill_ad2_mask, 'add_2'] = df_raw_data.loc[fill_ad2_mask, 'add_3'] # 清空已经被移到左侧的add_3原值 clear_ad3_mask = (df_raw_data['add_3'] == df_raw_data['add_1']) | (df_raw_data['add_3'] == df_raw_data['add_2']) df_raw_data.loc[clear_ad3_mask, 'add_3'] = np.nan
效果说明
处理后结果完全符合预期:
- 原行
add_1=NaN, add_2='XX路', add_3='YY号'→add_1='XX路', add_2='YY号', add_3=NaN - 原行
add_1=NaN, add_2=NaN, add_3='ZZ小区'→add_1='ZZ小区', add_2=NaN, add_3=NaN - 原行
add_1='AA街', add_2=NaN, add_3='BB栋'→add_1='AA街', add_2='BB栋', add_3=NaN - 原三列均非空的行不会做任何改动,原ID索引、其他非地址列全程保留,不需要额外做合并操作。
如果你后续要增加地址列,只需要把新列名加到
addr_columns列表里即可,左移逻辑不需要改动。
内容的提问来源于stack exchange,提问作者Catríona
相关产品推荐
相关产品推荐

