保存Pandas DataFrame为CSV时,如何避免numpy ndarray列转为字符串?
解决Pandas DataFrame中numpy数组列读写CSV时类型丢失的问题
你有一个包含ID列和Vector列(每个元素为形状(1,500)的numpy ndarray)的Pandas DataFrame,保存为CSV后重新读取,Vector列的数组会变成字符串类型,无法直接用于后续计算。
问题复现
保存前Vector列元素为numpy.ndarray类型:
>>> DataFrame_example["Vector"][0] Out: array([[-4.51561287e-02, -5.02060959e-03, 1.01038935e-02, -3.24810972e-03, 8.50208327e-02, -3.12430300e-02, -3.06447037e-02, -6.82420060e-02, 4.08798642e-02 ........................................... -6.08731210e-02, 4.24617827e-02, 2.90670991e-02, 1.87119041e-02, 5.67540973e-02, 4.65381369e-02, 3.42479758e-02, 9.88676678e-03, -1.62497200e-02, 1.46159781e-02, -6.39008060e-02]], dtype=float32) >>> type(DataFrame_example["Vector"][0]) Out: numpy.ndarray
保存为CSV并重新读取后,元素变为字符串:
>>> DataFrame_example["Vector"][0] '[[-4.51561287e-02 -5.02060959e-03 1.01038935e-02 -3.24810972e-03\n 8.50208327e-02 -3.12430300e-02 -3.06447037e-02 -6.82420060e-02\n 4.08798642e-02 2.49120360e-03 -6.40684515e-02 ............................................................................................ -5.22072986e-02\n 6.16791770e-02 -8.88353493e-03 1.65628344e-02 -5.95084354e-02\n -8.45786110e-02 -8.65871832e-03 3.98499370e-02 -3.41838486e-02\n -2.02250257e-02 5.18149361e-02 -5.80132604e-02 7.66506651e-03\n -5.49656115e-02 -6.08731210e-02 4.24617827e-02 2.90670991e-02\n 1.87119041e-02 5.67540973e-02 4.65381369e-02 3.42479758e-02\n 9.88676678e-03 -1.62497200e-02 1.46159781e-02 -6.39008060e-02]]'
当前读写代码:
保存:
compression_opts = dict(method='zip', archive_name=save_name+'.csv') DataFrame_example.to_csv(save_name+'.zip', index=False, compression=compression_opts)
读取:
DataFrame_example=pd.read_csv("example.csv")
下面是几种可行的解决方案:
方法1:将数组展开为多列保存
CSV是表格型格式,适合存储扁平数据。可以把(1,500)的数组拆分成500个单独的列,保存后读取时直接保留数值类型,后续需要时再合并回数组。
保存代码
import pandas as pd # 展开Vector列的数组为500列 vector_df = DataFrame_example['Vector'].apply(pd.Series).rename(columns=lambda x: f'Vector_{x}') # 合并ID列和展开后的列 final_df = pd.concat([DataFrame_example['ID'], vector_df], axis=1) # 保存为压缩CSV compression_opts = dict(method='zip', archive_name='expanded_data.csv') final_df.to_csv('expanded_data.zip', index=False, compression=compression_opts)
读取代码
import pandas as pd import numpy as np # 读取展开后的CSV final_df = pd.read_csv('expanded_data.zip') # 合并回(1,500)的numpy数组 DataFrame_example = final_df[['ID']].assign( Vector=final_df.filter(like='Vector_').apply(lambda row: row.to_numpy().reshape(1, 500), axis=1) )
方法2:使用Pickle序列化保存
Pickle是Python原生的序列化格式,可以完整保留numpy数组的类型和结构,无需转换。
保存代码
# 保存为压缩pickle文件 DataFrame_example.to_pickle('data.pkl.gz', compression='gzip')
读取代码
# 直接读取pickle文件,保留原类型 DataFrame_example = pd.read_pickle('data.pkl.gz')
注意:Pickle只能在Python环境中读取,不适合跨语言场景。
方法3:读取时将字符串转回numpy数组
如果必须使用CSV格式,可以在读取后把字符串列手动转换回numpy数组。
读取转换代码
import pandas as pd import numpy as np def str_to_array(s): # 去掉前后的[[和]],替换换行和多余空格为单一空格 cleaned = s.strip('[]').replace('\n', '').replace(' ', ' ') # 分割成数值字符串并转换为numpy数组 arr = np.fromstring(cleaned, sep=' ', dtype=np.float32).reshape(1, 500) return arr # 读取CSV并转换Vector列 DataFrame_example = pd.read_csv('example.csv') DataFrame_example['Vector'] = DataFrame_example['Vector'].apply(str_to_array)
注意:这种方法依赖字符串格式的稳定性,如果数组的字符串表示有变化(比如分隔符、括号格式),可能会转换失败。
方法4:使用HDF5格式存储
HDF5是适合存储大规模数值数据的格式,支持高效读写和保留数据类型,适合处理带numpy数组的DataFrame。
保存代码
# 保存为HDF5文件 DataFrame_example.to_hdf('data.h5', key='df', mode='w')
读取代码
# 读取HDF5文件 DataFrame_example = pd.read_hdf('data.h5', key='df')
内容的提问来源于stack exchange,提问作者Fatih G.
相关产品推荐
相关产品推荐

