pandas之自动优化数据类型

前言

pandas作为一款优秀的数据处理工具库正在逐渐的被大家喜爱,但是在一些规模较大的数据场景下,有时候却又显的捉襟见肘,我相信平日里大家都试过各种优化的方法,例如:

  • 主动删除垃圾 del some_garbage , 调用Python的垃圾回收库 gc 完成对冗余的内存的清除 gc.collect()
  • 尽量使用numpy数组运算来替换 for 循环和 apply 操作;
  • 数据存储方面使用更加高效的 leather 或者 parquet 等文件格式。
数据类型转换

除了上面这些方法之外,我们还可以在数据类型上做点文章,因为在某些场景下,pandas默认的数据类型的容量可能远远大于当前的数据规模,我们完全可以使用子类型对它进行替换:

Pandas TypeNumpy TypePython TypeUsage
objectstring_, unicodestrText
int64int, int8, int16, int32, int64, uint8, uint16, uint32, uint64intInteger numbers
float64float, float16, float32, float64floatFloat point numbers
boolbool_boolTrue/False values
datetime64datetime64[ns]NADate and time values
timedelta[ns]NANADifference between two datetimes
categoryNANAFinite list of text values

图表来源:http : //pbpython.com/pandas_dtypes.html

Data typeDescription
bool_Boolean(True or False) stored as a byte
int_Default integer type(same as C 1ong ; normally either int64or int32)
intcldentical to C int(normally int32 or int64)
intpInteger used for indexing(same as C ssize_t; normally either int32 or int64)
int8Byte(-128 to 127)
int16Integer(-32768 to 32767)
int32Integer(-2147483648 to 2147483647)
int64Integer(-9223372036854775808 to 9223372036854775807)
uint8Unsigned integer(0 to 255)
uint16Unsigned integer(0 to 65535)
uint32Unsigned integer(0 to 4294967295)
uint64Unsigned integer(0 to 18446744073709551615)
float_Shorthand for float64.
float16Half precision float: sign bit,5 bits exponent,10 bits mantissa
float32Single precision float: sign bit,8 bits exponent,23 bits mantissa
float64Double precision float: sign bit,11 bits exponent,52 bits mantissa
complex_Double precision float: sign bit,11 bits exponent,52 bits mantissa
complex64Complex number, represented by two 32-bit floats(real and imaginary components)
complex128Complex number, represented by two 64-bit floats(real and imaginary components)

图表来源:https : //docs.scipy.org/doc/numpy-1.13.0/user/basics.types.html

我们希望将类型简单化,以此节省内存,比如将 浮点数 转换为float16/32,或者将具有 正整数和负整数 的列转为 int8/16/32,还可以将 布尔值 转换为 uint8,甚至仅使用正整数来进一步减少内存消耗。

由此我们可以根据上面的数据类型将 浮点数和整数 转换为它们的 最小子类型

def reduce_memory_usage(df, verbose=True):
    numerics = ["int8", "int16", "int32", "int64", "float16", "float32", "float64"]
    start_mem = df.memory_usage().sum() / 1024 ** 2
    for col in df.columns:
        col_type = df[col].dtypes
        if col_type in numerics:
            c_min = df[col].min()
            c_max = df[col].max()
            if str(col_type)[:3] == "int":
                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                    df[col] = df[col].astype(np.int8)
                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                    df[col] = df[col].astype(np.int16)
                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                    df[col] = df[col].astype(np.int32)
                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
                    df[col] = df[col].astype(np.int64)
            else:
                if (
                    c_min > np.finfo(np.float16).min
                    and c_max < np.finfo(np.float16).max
                ):
                    df[col] = df[col].astype(np.float16)
                elif (
                    c_min > np.finfo(np.float32).min
                    and c_max < np.finfo(np.float32).max
                ):
                    df[col] = df[col].astype(np.float32)
                else:
                    df[col] = df[col].astype(np.float64)
    end_mem = df.memory_usage().sum() / 1024 ** 2
    if verbose:
        print(
            "Mem. usage decreased to {:.2f} Mb ({:.1f}% reduction)".format(
                end_mem, 100 * (start_mem - end_mem) / start_mem
            )
        )
    return df

上述代码仅限于数值型的数据,在真实生产环境下,我们可能遇到最多的就是 Object 类型的数据,很是头疼,那么有没有什么好的方法进行转换呢?
答案是肯定的,pandas内有已经封装好了的自动处理数据类型的方法:

df.convert_dtypes()
参考文献

微信公众号【东哥起飞】:
爆减内存!pandas自动优化骚操作
变量类型自动转换

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值