如何在Python中保存大型结构化numpy数组?
解决方案
方法1:纯文本保存+手动指定dtype加载
np.savetxt不会自动保留结构化数组的字段名和dtype信息,所以需要手动写入表头并在加载时指定原dtype:
保存代码
import numpy as np # 假设你的结构化数组变量名为arr arr = np.array([(0.358174, -0.508718, 2728, 0.103, 23.255, 22.633, 22.459, 21.911, 21.211, 0.487, 0.126, 0.145, 0.129, 0.264, 23.028, 22.621, 22.563, 22.039, 21.24 , 0.378, 0.164, 0.14 , 0.125, 0.248, 3, 1), (3.881584, -0.209449, 5052, 0.075, 22.778, 22.741, 22.187, 21.901, 21.29 , 0.308, 0.128, 0.124, 0.148, 0.345, 22.801, 22.859, 22.291, 22.047, 21.441, 0.285, 0.141, 0.119, 1.056, 0.323, 3, 0)], dtype=[('ra', '<f8'), ('dec', '<f8'), ('run', '<i2'), ('rExtSFD', '<f8'), ('uRaw', '<f8'), ('gRaw', '<f8'), ('rRaw', '<f8'), ('iRaw', '<f8'), ('zRaw', '<f8'), ('uErr', '<f8'), ('gErr', '<f8'), ('rErr', '<f8'), ('iErr', '<f8'), ('zErr', '<f8'), ('uRawPSF', '<f8'), ('gRawPSF', '<f8'), ('rRawPSF', '<f8'), ('iRawPSF', '<f8'), ('zRawPSF', '<f8'), ('upsfErr', '<f8'), ('gpsfErr', '<f8'), ('rpsfErr', '<f8'), ('ipsfErr', '<f8'), ('zpsfErr', '<f8'), ('type', '<i2'), ('ISOLATED', '<i4')]) # 根据字段dtype生成格式符列表 fmt = [] for field in arr.dtype.names: if np.issubdtype(arr.dtype[field], np.integer): fmt.append('%d') else: fmt.append('%.6f') # 可根据需求调整小数位数 # 写入txt,表头为字段名,用逗号分隔 np.savetxt('structured_data.txt', arr, fmt=fmt, delimiter=',', header=','.join(arr.dtype.names), comments='')
加载代码(硬编码dtype)
# 定义与原数组完全一致的dtype target_dtype = [('ra', '<f8'), ('dec', '<f8'), ('run', '<i2'), ('rExtSFD', '<f8'), ('uRaw', '<f8'), ('gRaw', '<f8'), ('rRaw', '<f8'), ('iRaw', '<f8'), ('zRaw', '<f8'), ('uErr', '<f8'), ('gErr', '<f8'), ('rErr', '<f8'), ('iErr', '<f8'), ('zErr', '<f8'), ('uRawPSF', '<f8'), ('gRawPSF', '<f8'), ('rRawPSF', '<f8'), ('iRawPSF', '<f8'), ('zRawPSF', '<f8'), ('upsfErr', '<f8'), ('gpsfErr', '<f8'), ('rpsfErr', '<f8'), ('ipsfErr', '<f8'), ('zpsfErr', '<f8'), ('type', '<i2'), ('ISOLATED', '<i4')] # 加载数据,跳过表头行 data = np.loadtxt('structured_data.txt', delimiter=',', dtype=target_dtype, skiprows=1) # 验证结果 print(data.dtype.names[:5]) # 输出:('ra', 'dec', 'run', 'rExtSFD', 'uRaw')
加载代码(动态读取表头)
如果不想硬编码dtype,可以先读取表头,再结合预定义的类型映射生成dtype:
# 读取文件表头 with open('structured_data.txt', 'r') as f: field_names = f.readline().strip().split(',') # 字段名到类型的映射,与原数组一致 type_map = { 'ra': '<f8', 'dec': '<f8', 'run': '<i2', 'rExtSFD': '<f8', 'uRaw': '<f8', 'gRaw': '<f8', 'rRaw': '<f8', 'iRaw': '<f8', 'zRaw': '<f8', 'uErr': '<f8', 'gErr': '<f8', 'rErr': '<f8', 'iErr': '<f8', 'zErr': '<f8', 'uRawPSF': '<f8', 'gRawPSF': '<f8', 'rRawPSF': '<f8', 'iRawPSF': '<f8', 'zRawPSF': '<f8', 'upsfErr': '<f8', 'gpsfErr': '<f8', 'rpsfErr': '<f8', 'ipsfErr': '<f8', 'zpsfErr': '<f8', 'type': '<i2', 'ISOLATED': '<i4' } # 构建dtype列表 target_dtype = [(name, type_map[name]) for name in field_names] # 加载数据 data = np.loadtxt('structured_data.txt', delimiter=',', dtype=target_dtype, skiprows=1) # 验证结果 print(data.dtype.names[:5])
方法2:二进制保存(保留完整dtype)
如果可以接受非纯文本的保存方式,np.savez会完整保留数组的结构化信息,无需手动处理dtype:
保存代码
# 保存数组到压缩二进制文件 np.savez('structured_data.npz', arr=arr) # 可选:单独保存字段名到txt文件(方便查看) with open('field_names.txt', 'w') as f: f.write('\n'.join(arr.dtype.names))
加载代码
# 加载npz文件 loaded_data = np.load('structured_data.npz') data = loaded_data['arr'] # 验证结果 print(data.dtype.names[:5])
内容的提问来源于stack exchange,提问作者Fitzroy
相关产品推荐
相关产品推荐

