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

DataFrame含列表值列转Categorical报错,求内存优化方案

解决含列表的Object列转Categorical报错及内存优化问题

首先,你遇到的TypeError: unhashable type: 'list'是因为Categorical类型要求元素必须是可哈希的——而列表是可变对象,无法被哈希,所以不能直接作为Categorical的类别值。结合你提到的「多数列表值均不同」的情况,转Categorical其实也起不到明显的内存优化效果(因为类别数量太多,和原Object列的内存占用差异不大),下面给你几个更适合的解决方案:

1. 先将列表转为可哈希类型(解决报错,但内存优化有限)

如果只是想解决报错,可以把列表转换成不可变的元组(元组是可哈希的),再转Categorical:

# 将列表转为元组
vs_df['handled_plans_id'] = vs_df['handled_plans_id'].apply(tuple)
# 转为Categorical类型
vs_df['handled_plans_id'] = vs_df['handled_plans_id'].astype('category')

不过注意:如果你的列表绝大多数都是唯一的,这种方法的内存优化效果会非常有限,因为Categorical的优势在于重复值多的场景。

2. 使用PyArrow列表类型(高效内存优化,推荐)

对于存储列表的列,用PyArrow的列式存储类型替代原生Object列,能大幅降低内存占用,同时不需要改变数据结构:

import pyarrow as pa
from pandas import ArrowDtype

# 将列转为PyArrow的列表类型
vs_df['handled_plans_id'] = vs_df['handled_plans_id'].astype(ArrowDtype(pa.list_(pa.int64())))

PyArrow会以更紧凑的二进制格式存储列表数据,比原生Object列(每个列表都是独立的Python对象)节省大量内存,尤其适合大数据集。

3. 序列化列表为Bytes类型

把列表序列化后存储为Bytes对象,也能减少内存占用,代价是存取时需要额外的序列化/反序列化步骤:

import pickle

# 序列化列表为bytes
vs_df['handled_plans_id'] = vs_df['handled_plans_id'].apply(pickle.dumps)

# 读取时反序列化
vs_df['handled_plans_id'] = vs_df['handled_plans_id'].apply(pickle.loads)

这种方法的内存节省效果不如PyArrow,但实现简单,适合对性能要求不高的场景。

4. 拆分列表为多列(适合列表长度固定或差异小的场景)

如果你的列表长度比较固定(比如最多包含2个元素),可以把列表拆成多个数值列,用更高效的数值类型存储:

# 拆分列表为两列,空值填充NaN
vs_df[['plan_1', 'plan_2']] = pd.DataFrame(vs_df['handled_plans_id'].tolist(), index=vs_df.index)
# 转为int类型(空值用pd.NA)
vs_df[['plan_1', 'plan_2']] = vs_df[['plan_1', 'plan_2']].astype(pd.Int64Dtype())

这种方法内存占用最低,但只适合列表长度相对统一的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:49:38