astype()降精度不省内存反增倍,因nan致隐式升为int32对象类型;category仅在唯一率≤10%时省内存;批量转换须用字典指定列,datetime需先to_datetime清洗,gb数据优先读取时设dtype。

直接用 astype() 降精度不等于省内存,反而可能翻倍——关键在选对类型、避开 NaN 和唯一率陷阱。
为什么 astype("int32") 后内存反而变大?
常见现象:原始列是 int64,含少量 NaN,一执行 df["col"].astype("int32"),内存涨了 2 倍。
原因不是转换本身,而是 pandas 的隐式升级:int32 不支持 NaN,所以它自动切到 Int32(带 nullable 的 object-like 类型),底层是 Python 对象数组,开销远超原生 int32。
- 先检查空值:
df["col"].isna().sum(),非零就别硬转原生整数 - 含
NaN的数值列,改用pd.Int32Dtype()(注意不是字符串"Int32") - 若必须用原生类型,先填或删
NaN:df["col"].fillna(0).astype("int32")
astype("category") 在什么情况下更占内存?
category 看似省空间,但只对低基数(low-cardinality)文本列有效。一旦唯一值比例超过 50%,它比原始 object 还吃内存。
判断方法:df["col"].nunique() / len(df)
- ≤ 0.1:放心转
"category" - 0.1–0.5:可试,但建议先
df["col"].value_counts().head(10)看分布是否集中 - > 0.5:别转,改用
"string"(pandas 1.0+)更稳,内存略高但无编码错乱风险
批量 astype() 时最常踩的三个坑
写循环或字典批量设 dtype 很常见,但容易忽略底层行为:
-
df.astype("category", inplace=True)无效 —— 它只对单列生效,多列必须传字典:df = df.astype({"a": "category", "b": "float32"}) -
astype()默认返回新对象,不修改原df;inplace=True对部分类型(如category)也不起作用,必须显式赋值 - datetime 列别用
astype("datetime64[ns]")硬转 —— 若原始是混杂格式字符串,会直接报ValueError: Unable to parse datetime;应先pd.to_datetime(..., errors="coerce")清洗
处理 GB 级数据时,astype() 本身可能触发 MemoryError
因为 astype() 默认深拷贝,临时内存峰值≈原数组 + 新数组。GB 数据一转就崩。
- 优先在读取阶段指定类型:
pd.read_csv(..., dtype={"id": "int32", "price": "float32"}) - 必须后处理时,用分块:
pd.read_csv(..., chunksize=50000),每块单独astype并保存/追加 - 超大 NumPy 数组慎用
copy=False—— 它仅在类型兼容(如 float64→float32)且不涉及内存重排时生效,多数情况仍拷贝
真正难的不是“怎么写 astype”,而是“哪一列该转、转成什么、有没有隐藏的 NaN 或边界值”。每次执行前花 30 秒查 .dtypes、.isna().sum()、.nunique(),比盲目跑完再调优省三小时。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











