用 df.dtypes 查看真实类型,避免误判混合数据为数值型;对 object 列用 apply(type).unique() 探查内部类型,用 pd.to_numeric(..., errors='coerce') 安全转数字,读取时通过 dtype 或 converters 预控类型。

用 df.dtypes 看清真实类型,别信列名或前几行
很多人一上来就 df.head(),发现某列显示的都是数字,就默认它是 int64 或 float64,结果后续 .sum() 报错:TypeError: unsupported operand type(s) for +: 'int' and 'str'。这是因为 pandas 在混合类型(比如数字混着空字符串、"N/A"、"NULL")时会自动退化为 object 类型,但内部元素类型并不统一。
正确做法是先看 df.dtypes,再对 object 类型列做进一步探查:
- 用
df[col].apply(type).unique()查真实 Python 类型 - 用
df[col].apply(lambda x: str(x).strip()).nunique()判断是否只是空格/大小写导致的“假混合” - 用
pd.api.types.is_string_dtype(df[col])或pd.api.types.is_numeric_dtype(df[col])做语义判断,比单纯看dtype更可靠
用 pd.to_numeric(..., errors='coerce') 安全转数字,别用 astype(int)
直接 df['col'].astype(int) 遇到非数字内容立刻崩,而 pd.to_numeric() 的 errors='coerce' 会把非法值转成 NaN,保留结构可继续处理。这是最常用也最稳妥的清洗入口。
注意三个关键参数组合:
-
errors='coerce':强制转,错则填NaN(推荐首选) -
errors='ignore':不转,原样返回(基本没用) -
downcast='integer':转完再压缩类型(比如从int64降到int8),省内存但需确认无溢出
示例:df['price'] = pd.to_numeric(df['price'], errors='coerce', downcast='integer')。如果之后要 fillna,记得先判断是否真需要补 0 还是留 NaN —— 补 0 可能扭曲统计结果。
对多列批量处理时,用 select_dtypes('object') 锁定目标,再按需分组
一次性处理几十列时,不能靠肉眼挑 object 列。用 df.select_dtypes('object').columns 拿到所有疑似混合列,再结合业务逻辑分组处理:
inference.sh 的 Python SDK:运行 AI 应用、构建智能体,并集成 150 多个模型。包名:inferencesh (pip install inferencesh)。支持同步/异步……
- 数值型字段(如 "age", "score", "quantity")→ 全部走
pd.to_numeric(..., errors='coerce') - 分类型字段(如 "status", "category")→ 用
df[col].str.strip().str.lower()标准化,再.astype('category')节省内存 - 时间字段(如 "created_at")→ 优先试
pd.to_datetime(df[col], errors='coerce'),失败再看是否含非标准格式(如带中文“年月日”)
避免对所有 object 列无差别 .astype(str) —— 这会让后续数字解析更难,且丢失原始结构信息。
混合类型常藏在读取阶段,read_csv 的 dtype 和 converters 要提前设
很多问题其实在 pd.read_csv() 时就能规避。默认读取会触发类型推断,一旦某列中间插入异常值,整列变 object,后面清洗成本翻倍。
两种预控方式:
- 显式指定
dtype:pd.read_csv('x.csv', dtype={'price': 'float64', 'id': 'string'})(注意 pandas 1.3+ 支持'string'类型) - 用
converters做逐行清洗:converters={'amount': lambda x: float(x.replace(',', '')) if x.strip() else np.nan}
特别提醒:dtype 参数无法处理含空值的整数列(pandas 不支持 int with NaN),必须用 Int64(首字母大写)或先读成 float64 再转 Int64。
混合类型不是 bug,是数据现实的快照。真正麻烦的是那些看似干净、实则藏了不可见空格、零宽字符、BOM 头的列——它们不会报错,但会让 .nunique() 和 .groupby() 给出错误结果。建议对关键列加一道 df[col].str.encode('utf-8').str.startswith(b'\xef\xbb\xbf') 检查 BOM。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










