如何过滤<class 'str'>类型数据并返回True/False实现数据校验?
问题说明
现有百万行级数据集需做数据校验,标记各字段中字符串、整数、浮点数等类型的异常值。在尝试schema、pandera等数据校验库后发现,需要先将read_csv默认读取为全字符串类型的DataFrame列,转换为对应真实数据类型才能开展后续校验。
示例读取得到的数据集全列均为字符串类型,内容如下:
| Index | Item | Quantity | Price |
|---|---|---|---|
| 0 | Apple | 20 | 30.5 |
| 1 | Banana | 5 | 3.4 |
| 2 | Coke | 3 | 1.2 |
| 3 | 123 | Dough | Ele |
| 4 | Ham | 85.6 | Pear |
| 5 | 56.1 | 9 | 20 |
现有如下尝试编写的类型判断函数,期望对列做过滤后返回布尔值:
def check_type(x): try: return type(eval(x)) except Exception as e: return type(x) df.applymap(check_type)
核心诉求:确认该写法是否可以实现类似not <class 'str'> in df['Item'] returns True的判断逻辑。
解答
你当前的写法实现不了目标判断逻辑,存在两个明显问题:
- 安全风险极高:
eval()会直接执行传入字符串里的可执行代码,只要数据单元格里注入了恶意代码,运行时会直接在本地环境执行,绝对不能用在来源不完全可控的数据集处理场景。 - 逻辑不匹配:
df.applymap(check_type)返回的是和原表结构一致、每个单元格存储对应值解析后类型对象的新DataFrame,直接用<class 'str'>做in df['Item']判断,本质是在原始列的字符串值里查找类型对象,永远拿不到正确结果。
可落地的实现方案
针对百万行级数据的处理场景,优先选性能更高、无安全隐患的实现方式:
- 先写无安全风险的类型识别函数,替代eval逻辑
import pandas as pd from typing import Type def get_value_type(x: str) -> Type: # 处理空值场景 if pd.isna(x): return type(None) x = x.strip() # 匹配整数 if x.lstrip('-').isdigit(): return int # 匹配浮点数 try: float(x) return float except ValueError: # 其余值归为字符串 return str
- 生成全表类型矩阵后,即可实现你需要的整列布尔判断
# 生成每个单元格对应类型的DataFrame type_df = df.applymap(get_value_type) # 判断Item列是否全为字符串:全是字符串返回True,存在其他类型返回False item_all_str = not (type_df['Item'] != str).any() # 判断Quantity列是否存在字符串类型异常值 quantity_has_str_error = (type_df['Quantity'] == str).any()
- 要直接筛选异常值行,用布尔索引即可,比如筛选Price列里存了非数值字符串的异常行:
price_error_rows = df[type_df['Price'] == str]
性能优化提示:百万行规模下逐行apply的处理速度偏慢,如果只需要判断列是否能转为数值类型,可以直接用pandas原生的
pd.to_numeric方法,处理速度比逐行apply快3~10倍:# 快速标记Quantity列里无法转为数值的异常位置 quantity_invalid_mask = pd.to_numeric(df['Quantity'], errors='coerce').isna()
内容的提问来源于stack exchange,提问作者H_SOCIAL MEDIA
相关产品推荐
相关产品推荐

