老码农和你一起学AI:Python系列-Pandas内存压缩

处理数据时,是不是好会遇到这种情况:明明只是想分析一份用户信息表,却突然弹出 “内存不足” 的提示 —— 表格里的年龄、职业、手机号挤在内存里,像被胡乱塞进储物箱的杂物,明明总容量够,却因为摆放不当而塞不下。内存压缩技术,就是给数据做 “收纳整理” 的学问。它不只是程序员的专业工具,更是理解数据本质的钥匙:那些看似必须占据大量空间的数字和文字,其实藏着许多可以精简的秘密。

一、类型降级的智慧

处理数据时,我们常常默认用 “最大号容器” 装数据。比如记录用户年龄时,Python 的 pandas 会默认用 int64 类型 —— 这种类型能存储从 - 9223372036854775808 到 9223372036854775807 的数字,足够装下宇宙年龄(约 138 亿年)。但现实中,年龄最多不过 120 左右,用能装下 138 亿的容器装 120,就像用行李箱装一支笔,纯属浪费。

类型降级就是把 “大容器” 换成 “小抽屉”。比如用 int16 替代 int64:int16 能存储 - 32768 到 32767 的数字,装年龄绰绰有余,却能把内存占用砍掉 75%。在 pandas 里,只需一行代码就能完成这种转换:


import pandas as pd

# 生成一份模拟用户数据:100万条年龄记录(1-120岁)

data = {'age': [i % 120 + 1 for i in range(1000000)]}

df = pd.DataFrame(data)

# 查看原始类型(默认int64)和内存占用

print("原始类型:", df['age'].dtype)

print("原始内存(MB):", df['age'].memory_usage(deep=True) / 1024 / 1024)

# 类型降级:从int64转为int16

df['age'] = df['age'].astype('int16')

# 查看转换后的数据

print("转换后类型:", df['age'].dtype)

print("转换后内存(MB):", df['age'].memory_usage(deep=True) / 1024 / 1024)

运行后会发现,原本需要约 7.6MB 的年龄数据,压缩后只剩 1.9MB。这种压缩的本质,是对数据范围的精准判断:当我们知道数据不会超过某个范围时,就没必要保留多余的存储空间。就像快递打包时,知道物品是手机,就不会用装冰箱的箱子。

二、Category 类型

字符串是内存的 “空间杀手”。比如一份电商订单表,“商品类别” 字段里反复出现 “服装”“电子产品”“食品”—— 假设这三个词各出现 100 万次,每个词按 10 个字符计算,直接存储需要 3000 万字符的空间。但仔细想想:这些词翻来覆去就是那几个,何必重复存储?

Category 类型的解决思路很简单:给重复字符串 “编序号”。比如用 0 代表 “服装”,1 代表 “电子产品”,2 代表 “食品”。存储时只保留序号(整数),需要显示时再把序号换回字符串。这样一来,100 万条 “服装” 记录,从存储 100 万个 “服装” 字符串,变成存储 100 万个 0—— 整数比字符串占用的空间小得多。

用 pandas 实现这种压缩同样直观:


# 生成模拟订单数据:300万条记录,商品类别只有3种

categories = ['服装', '电子产品', '食品']

data = {'category': [categories[i % 3] for i in range(3000000)]}

df = pd.DataFrame(data)

# 查看原始类型(object)和内存占用

print("原始类型:", df['category'].dtype)

print("原始内存(MB):", df['category'].memory_usage(deep=True) / 1024 / 1024)

# 转换为Category类型

df['category'] = df['category'].astype('category')

# 查看转换后的数据

print("转换后类型:", df['category'].dtype)

print("转换后内存(MB):", df['category'].memory_usage(deep=True) / 1024 / 1024)

这段代码会告诉你:原本需要约 28MB 的字符串数据,用 Category 类型后可能只剩 2.8MB—— 压缩率高达 90%。但要注意,这种方法只适合重复率高的字符串:如果每个字符串都是独一无二的(比如订单号),编号反而会多占空间,就像给每个陌生人起一个专属代号,不如直接记名字省事。

三、内存占用分析

盲目压缩往往事倍功半。比如有些字段看似重复率高,实际却藏着很多变种(比如 “服装” 和 “服饰” 是不同字符串);有些数字看似范围小,却可能突然出现超大值(比如记录收入时,大部分人是几千到几万,但少数人是上亿)。这时候,我们需要先给数据做 “内存体检”。

pandas 的df.info(memory_usage='deep')就是最好的 “体检工具”。它能显示每个字段的真实内存占用(包括字符串的实际长度),帮我们找到最该压缩的 “重灾区”:


# 结合前面的用户表和订单表,生成一份混合数据

user_data = {'age': [i % 120 + 1 for i in range(1000000)],

'city': ['北京', '上海', '广州', '深圳'][i % 4] for i in range(1000000)}

df = pd.DataFrame(user_data)

# 执行内存体检

print("数据内存体检结果:")

df.info(memory_usage='deep')

运行后会看到类似这样的输出:


<class 'pandas.core.frame.DataFrame'>

RangeIndex: 1000000 entries, 0 to 999999

Data columns (total 2 columns):

# Column Non-Null Count Dtype

--- ------ -------------- -----

0 age 1000000 non-null int64

1 city 1000000 non-null object

dtypes: int64(1), object(1)

memory usage: 45.7 MB

从结果能清晰看到:age 字段用了 int64(可降级),city 字段是 object 类型(重复率高,可转 Category)。有了这份 “体检报告”,压缩就能有的放矢 —— 先把 age 转 int16,再把 city 转 Category,最终内存可能从 45.7MB 降到 5MB 左右。

四、数据理解的镜像

内存压缩技术的深层价值,在于它迫使我们更了解数据。当我们思考 “这个字段能不能用 int16 存储” 时,其实是在问 “这些数据的合理范围是什么”;当我们判断 “是否该用 Category 类型” 时,其实是在分析 “这些字符串的重复规律是什么”。就像整理衣柜时,你会自然记住 “冬天的衣服厚重且只穿半年”“袜子总是成打出现”—— 对数据的理解,会随着压缩过程逐渐清晰。

如今,随着数据量爆炸式增长,内存压缩早已不是 “可选技能”。它可能是让老旧电脑流畅运行数据分析的关键,也可能是大型系统降低成本的核心策略。但无论应用在什么场景,它的本质始终没变:用智慧替代蛮力,用对数据的理解替代对空间的浪费。

最后小结:

梳理一下,今天梳理了内存压缩的三种核心方法及相关实践:

  • 类型降级:数据默认存储常使用 “大容器”,比如 pandas 会用 int64 类型记录年龄,而这种类型能存储的数值范围远大于实际所需(年龄最多百余岁)。通过df.astype({'col': 'int16'})这类操作,将存储类型降级(如 int64 转为 int16),在数据范围允许的情况下可大幅节省空间,例如年龄数据的内存占用能减少 75%。
  • Category 类型处理重复字符串:重复出现的字符串(如电商订单中的 “服装”“电子产品” 等商品类别)直接存储会占用大量内存。使用category类型时,会给重复字符串编序号(以整数形式存储),需要显示时再转换回原字符串,对重复率高的字符串压缩率可达 90%,但不适合独一无二的字符串(如订单号)。
  • 内存占用分析:盲目压缩效率低,df.info(memory_usage='deep')可作为 “内存体检工具”,清晰显示各字段的真实内存占用情况,帮助定位压缩重点(比如识别可降级的数值字段、可转为 Category 类型的字符串字段),让压缩更有针对性。

内存压缩技术的深层价值在于,它不仅是节省空间的手段,更能推动对数据的理解 —— 思考如何压缩的过程,本质是分析数据的合理范围、重复规律等核心特征。在数据量激增的当下,它已成为提升设备运行效率、降低系统成本的重要技能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值