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

降低DataFrame内存占用:是否有比自定义dtype转换更高效的方法

现有实现的问题

你写的基础逻辑是对的,但存在几个影响性能和准确性的问题:

  • 存在笔误:has_decimal == 1是相等判断不是赋值,不过该变量后续未使用,不影响转换逻辑
  • any(df[col]%1!=0) 是行级遍历,大数据量下速度极慢,换成pandas内置向量化判断(df[col] % 1 != 0).any()效率会高很多
  • 没有处理无符号整数场景:如果列最小值≥0,用uint类型能进一步压缩空间,比如0~255的范围用uint8只占1字节,比int8的存储范围大一倍
  • 没有支持Nullable类型:pandas的Int8/Int16等支持空值的整数类型,遇到含NaN的整数列不会直接转成float,能进一步节省空间
  • 未覆盖字符串、布尔、时间等非纯数值类型的压缩场景,这类场景的压缩空间通常比数值类型更大

更高效的压缩方案

1. 基于pandas内置方法的高性能压缩实现

不需要自己手写边界判断逻辑,用pd.to_numeric的downcast参数就能自动适配最优数值类型,底层是C实现的逻辑,比纯Python循环判断快3~10倍,还能自动处理无符号整数、Nullable类型的场景:

import pandas as pd
from pandas.api.types import is_integer_dtype, is_float_dtype, is_object_dtype

def compress_df_dtypes(df):
    for col in df.columns:
        if is_integer_dtype(df[col]):
            df[col] = pd.to_numeric(df[col], downcast='integer')
        elif is_float_dtype(df[col]):
            df[col] = pd.to_numeric(df[col], downcast='float')
        # 额外补充字符串列的压缩,基数低于50%的列转category压缩效果极佳
        elif is_object_dtype(df[col]):
            unique_ratio = len(df[col].unique()) / len(df[col])
            if unique_ratio < 0.5:
                df[col] = df[col].astype('category')
    return df

2. 读文件阶段提前压缩

如果是从csv等文件加载数据,不需要先读成默认类型再转,读入时就指定类型可以省掉中间的内存占用峰值:

  • 先读10%的行做采样,推断最优类型,再按推断的类型读全量数据
  • 时间列直接指定parse_dates参数转成datetime64类型,不要存为字符串或者时间戳数值

3. 极端场景的定向优化

  • 精度要求不高的浮点列可以直接强制转成float16,比自动压缩的空间占比再降一半
  • 布尔值列显式转成boolean类型,单值仅占1字节,远小于默认的int类型
  • 取值固定的离散列优先用category类型存储,最高可节省90%以上的内存

内容的提问来源于stack exchange,提问作者gtomer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 10:27:01