You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在pandas的map()中获取值索引,同步实现数据清洗与错误值统计

问题场景

从CSV读取的DataFrame存在数据错位问题:部分值位于错误列(如'900'出现在ZIPCODE列、'RQ'出现在语言列而非国籍列),部分错误值需转为NaN,部分整行列偏移需单独处理。当前采用逐列map函数做数据清洗(例如用正则校验ZIPCODE列),希望在清洗的同时统计每行的错误值数量,但map函数无法访问对应值的索引;虽可分开统计错误值,但希望合并清洗与统计流程。

现有清洗代码示例:

import re
import numpy as np
import pandas as pd

def is_zipcode(value: str, regx):
    if regx.match(value):
        return value
    else:
        return np.nan

regx = re.compile(r"^[0-9]{5}(?:-[0-9]{4})?$")
df['ZIPCODE'] = df['ZIPCODE'].map(lambda x: is_zipcode(x, regx), na_action='ignore')

分开统计错误值的代码示例:

def is_zipcode_count(value: str, regx):
    if regx.match(value):
        return 0
    else:
        return 1

regx = re.compile(r"^[0-9]{5}(?:-[0-9]{4})?$")
df['badValues'] = df['ZIPCODE'].map(lambda x: is_zipcode_count(x, regx), na_action='ignore')
df['badValues'] = df['badValues'] + df['Nationalities'].map(is_nationality, na_action='ignore')

期望的合并逻辑:在清洗函数中直接更新对应行的错误计数。


可行解决方案

方案1:使用df.apply逐行处理(推荐)

利用apply可访问整行数据的特性,一次遍历完成列清洗与错误计数,适合需要复杂行级逻辑的场景(比如整行列偏移的特殊处理)。

代码示例:

import re
import numpy as np
import pandas as pd

# 预定义各列校验规则
zipcode_regx = re.compile(r"^[0-9]{5}(?:-[0-9]{4})?$")
valid_nationalities = {"CN", "US", "JP", "EU"}

def process_row(row):
    # 初始化错误计数
    if pd.isna(row['badValues']):
        row['badValues'] = 0
    
    # 处理ZIPCODE列
    if not pd.isna(row['ZIPCODE']):
        if not zipcode_regx.match(str(row['ZIPCODE'])):
            row['ZIPCODE'] = np.nan
            row['badValues'] += 1
    
    # 处理Nationalities列
    if not pd.isna(row['Nationalities']):
        if row['Nationalities'] not in valid_nationalities:
            row['Nationalities'] = np.nan
            row['badValues'] += 1
    
    # 其他列的清洗逻辑可在此添加
    return row

# 初始化错误计数列
df['badValues'] = 0
# 逐行处理数据
df = df.apply(process_row, axis=1)

方案2:结合mask批量处理(性能最优)

适合规则统一的批量校验场景,性能远高于逐行遍历,代码简洁易维护。

代码示例:

import re
import numpy as np
import pandas as pd

zipcode_regx = re.compile(r"^[0-9]{5}(?:-[0-9]{4})?$")
valid_nationalities = {"CN", "US", "JP", "EU"}

# 初始化错误计数列
df['badValues'] = 0

# 处理ZIPCODE列:标记错误值为NaN,同时累加错误数
zipcode_valid = df['ZIPCODE'].astype(str).str.match(zipcode_regx)
df['ZIPCODE'] = df['ZIPCODE'].mask(~zipcode_valid, np.nan)
df['badValues'] += (~zipcode_valid).astype(int)

# 处理Nationalities列
nationality_valid = df['Nationalities'].isin(valid_nationalities)
df['Nationalities'] = df['Nationalities'].mask(~nationality_valid, np.nan)
df['badValues'] += (~nationality_valid).astype(int)

方案3:iterrows逐行遍历(直观但性能差)

如果需要直接操作索引,可采用此方式,但大数据量下不推荐使用。

代码示例:

import re
import numpy as np
import pandas as pd

zipcode_regx = re.compile(r"^[0-9]{5}(?:-[0-9]{4})?$")
df['badValues'] = 0

for idx, row in df.iterrows():
    # 处理ZIPCODE列
    if not pd.isna(row['ZIPCODE']):
        if not zipcode_regx.match(str(row['ZIPCODE'])):
            df.at[idx, 'ZIPCODE'] = np.nan
            df.at[idx, 'badValues'] += 1
    # 其他列的清洗逻辑可在此添加

方案对比

  • 方案1:灵活性最高,支持复杂行级定制逻辑,小数据量首选;
  • 方案2:性能最优,适合规则统一的批量处理场景,大数据量首选;
  • 方案3:逻辑直观但性能最差,仅用于小型数据集或调试场景。

内容的提问来源于stack exchange,提问作者студент001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 11:24:24