如何基于现有DataFrame按字符串长度筛选异常ID生成新DataFrame
原有方案的问题:applymap生成的是与原DataFrame形状一致的布尔掩码,直接用该掩码索引原表会保留原有的两列结构,仅在掩码为True的位置保留原值,其余位置自动填充NaN,因此会得到带大量空值的结果,需要额外清理。
推荐实现方案
使用pandas内置的长表转换+向量化字符串判断实现,无多余空值,性能远优于逐元素apply,代码逻辑清晰:
import pandas as pd # 原示例数据 df = pd.DataFrame({'old_id':['111', '2222','3333', '4444'], 'new_id':['5555','6666','777','8888']}) # 提取所有长度不符合4位要求的ID,生成列名为id的单列DataFrame incorrect_id_df = ( df.melt(value_name='id') .query("id.str.len() != 4") [["id"]] .reset_index(drop=True) )
运行后输出结果完全匹配预期:
id 0 111 1 777
- 后续如果需要把错误ID转为字典,直接调用
incorrect_id_df.to_dict()即可。 - 如果需要保留错误ID的来源列(标记ID来自old_id还是new_id列),无需过滤
id列即可,代码如下:
# 带来源信息的错误ID表 incorrect_id_with_source = ( df.melt(value_name='id', var_name='source_column') .query("id.str.len() != 4") .reset_index(drop=True) )
原有写法的调整方式
如果要基于之前的applymap写法修改,可以通过stack自动剔除NaN值,再整理为目标格式,但这种写法依赖逐元素运算,效率较低,不适合大数据量场景:
incorrect_id_df = ( df[df.applymap(lambda x: len(x) != 4)] .stack() .rename("id") .reset_index(drop=True) .to_frame() )
内容的提问来源于stack exchange,提问作者amontes2019
相关产品推荐
相关产品推荐

