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

将Pandas数据帧写入Feather/Parquet时列表转numpy数组的问题求助

Pandas写入Feather/Parquet时list列自动转为numpy.ndarray的问题及解决办法

问题场景

用pd.to_feather()或pd.to_parquet()存储包含list类型列的Pandas数据帧,读取后原本的list列会被转成numpy.ndarray类型,导致依赖原生list的代码运行失败。改用pickle存储虽然能保留原类型,但文件体积直接涨到原来的4倍。当前使用版本:pandas 1.4.4、pyarrow 9.0.0。

可以用这段代码复现问题:

import pandas as pd

# 构造带list列的DataFrame
df = pd.DataFrame({'list_col': [[1, 2, 3], [4, 5, 6]]})
print(f"原始元素类型: {type(df['list_col'].iloc[0])}")  # 输出 <class 'list'>

# 写入Feather再读取
df.to_feather('demo.feather')
df_read = pd.read_feather('demo.feather')
print(f"读取后元素类型: {type(df_read['list_col'].iloc[0])}")  # 输出 <class 'numpy.ndarray'>

原因

这是因为Feather/Parquet依赖pyarrow引擎序列化数据,会把Python list转成Arrow的list类型;而在pandas 1.4.x这类老版本中,读取Arrow list类型时会默认转成numpy.ndarray,而且这个转换过程没有任何警告,很容易踩坑。

解决办法

1. 读取后手动转成list

既保留Feather/Parquet的体积优势,又能恢复原类型,适合不想升级版本的场景:

# 单列转换
df_read['list_col'] = df_read['list_col'].apply(lambda x: x.tolist())

# 多列批量转换
list_columns = ['list_col1', 'list_col2']  # 替换成你的列名
df_read[list_columns] = df_read[list_columns].applymap(lambda x: x.tolist())

2. 升级pandas版本

pandas 2.0及以上版本对Arrow类型的处理做了优化,默认会把Arrow list映射为pd.ListDtype,后续可以更方便地转成原生list,而且不会再无警告地转成numpy.ndarray。升级后能从根源避免这个问题。

3. 直接用pyarrow API控制序列化(进阶)

如果需要更精细的类型控制,可以绕过pandas的IO方法,直接用pyarrow操作:

import pyarrow as pa
import pyarrow.feather as feather

# 写入数据
table = pa.Table.from_pandas(df)
feather.write_feather(table, 'demo.feather')

# 读取时指定类型映射,直接转成原生list
table_read = feather.read_feather('demo.feather')
df_read = table_read.to_pandas(types_mapper=lambda dtype: dtype.to_pylist() if pa.types.is_list(dtype) else dtype)

关于pickle的补充

pickle虽然能完美保留原生类型,但缺点很明显:文件大、只能在Python环境用、不安全(不可信的pickle文件可能执行恶意代码),所以优先推荐上面的方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:40:57