python - 将 numpy ndarray 的子类存储在磁盘上后保存它
问题描述
假设我有一个array
从类子类化的实例np.ndarray
:
class RealisticInfoArray(np.ndarray):
def __new__(cls, input_array, info=None):
obj = np.asarray(input_array).view(cls)
obj.info = info
return obj
def __array_finalize__(self, obj):
if obj is None: return
self.info = getattr(obj, 'info', None)
def __reduce__(self):
print('in reduce')
# Get the parent's __reduce__ tuple
pickled_state = super(RealisticInfoArray, self).__reduce__()
# Create our own tuple to pass to __setstate__
new_state = pickled_state[2] + (self.info,)
# Return a tuple that replaces the parent's __setstate__ tuple with our own
return (pickled_state[0], pickled_state[1], new_state)
def __setstate__(self, state):
print('in set_state')
self.info = state[-1] # Set the info attribute
# Call the parent's __setstate__ with the other tuple elements.
super(RealisticInfoArray, self).__setstate__(state[0:-1])
def tofile(self, fid, sep="", format="%s"):
super().tofile(fid, sep, format)
print('in tofile')
def tobytes(self, order='C'):
super().tobytes(order)
print('in tobytes')
array = RealisticInfoArray(np.zeros((7, 9, 13)), info='tester')
方法__reduce__
, __setstate__
,tofile
和tobytes
被包括在内,因为我认为它们参与了我想要执行的保存:我想将数组存储在磁盘上(通过任何np.save
, np.savez
, np.savez_compressed
)并在保留该对象的类的同时将其加载回来以及所有的自定义属性。
我已经尝试过另一个 SO question的方法,但这不起作用,因为我想使用np
函数,而不是pickle
or dill
。另外,我从那里借用了 MWE 的子类。
另一点信息是实际保存由 执行np.lib.npyio.format.write_array
,这似乎不允许存储数据的任何自定义行为。
所以,我的问题是是否可以保留存储数组的类,如果可以,怎么做?
解决方案
现有的子类做什么? np.matrix
,np.recarray
和np.ma.MaskedArray
. 我没有测试他们save
或查看他们是否有特殊代码。 matrix
具有相同的属性和数据缓冲区,只是限制维度的方法。掩码数组同时具有data
和mask
数组属性。 recarray
就像一个具有不同索引方法的结构化数组。
scipy.sparse
有自己的save,savez
用来保存自己的属性。这也需要它自己的负载,以重新创建矩阵。 sparse
虽然不是子类。
以后我可能会做一些探索自己。
但不要对pickle
. np.save
和之间有着密切的联系pickle
。 np.save
是ndarray
,while的 pickle 方法,save
用于pickle
序列化对象元素。
不保留矩阵子类:
In [52]: np.save('matrix.npy',M)
In [53]: np.load('matrix.npy')
Out[53]:
array([[1, 2],
[3, 4]])
pickle
保留子类(省略演示)。
np.save
没有为掩码数组实现:
In [66]: ma = np.ma.masked_array(np.ones(4))
In [67]: ma
Out[67]:
masked_array(data=[1., 1., 1., 1.],
mask=False,
fill_value=1e+20)
In [68]: np.save('masked.npy',ma)
Traceback (most recent call last):
File "<ipython-input-68-3c39e0b0fc22>", line 1, in <module>
np.save('masked.npy',ma)
File "<__array_function__ internals>", line 6, in save
File "/usr/local/lib/python3.6/dist-packages/numpy/lib/npyio.py", line 529, in save
pickle_kwargs=dict(fix_imports=fix_imports))
File "/usr/local/lib/python3.6/dist-packages/numpy/lib/format.py", line 675, in write_array
array.tofile(fp)
File "/usr/local/lib/python3.6/dist-packages/numpy/ma/core.py", line 6116, in tofile
raise NotImplementedError("MaskedArray.tofile() not implemented yet.")
NotImplementedError: MaskedArray.tofile() not implemented yet.
再次泡菜工作:
In [69]: with open('masked.pkl','wb') as f:
...: pickle.dump(ma,f)
...:
In [70]: with open('masked.pkl','rb') as f:
...: pp=pickle.load(f)
...:
In [71]: pp
Out[71]:
masked_array(data=[1.0, 1.0, 1.0, 1.0],
mask=[False, False, False, False],
fill_value=1e+20)
推荐阅读
- nginx - Nginx 443 端口已经被它自己使用了?
- reactjs - 通过 React js 使用三元运算符进行具有 >2 条件的内联样式
- c++ - 使用半字节/亚 8 位值填充类似于 IP 标头的结构
- javascript - 如何在 svelte js 中突出显示活动的导航栏链接
- c# - 分配实体实例而不是实体 ID 创建新记录
- php - Laravel 中的模型可以应用多个查询吗?
- python - 为 Python 2.7 创建可执行文件
- ruby-on-rails - 具有特定 ID 的嵌套路由的 Rails 路由别名
- python - 不显示 discord.py 的更新角色
- macos - macOS 使用 kevents 监控新的分叉进程