【问题标题】:Saving subclass of numpy ndarray after storing it on disk将 numpy ndarray 的子类存储在磁盘上后保存它
【发布时间】:2021-01-13 09:43:57
【问题描述】:

假设我有一个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__tofiletobytes 包括在内,因为我认为它们参与了我想要执行的保存:我想将数组存储在磁盘上(通过任何@ 987654329@、np.saveznp.savez_compressed) 并将其加载回来,同时保留该对象的类和所有自定义属性。

我已经尝试过another SO question 的方法,但这不起作用,因为我想使用np 函数,而不是pickledill。另外,我从那里借用了 MWE 的子类。

另外一点信息是,实际的保存是由np.lib.npyio.format.write_array 执行的,这似乎不允许存储数据的任何自定义行为。

所以,我的问题是是否可以保留存储数组的类,如果可以,如何做?

【问题讨论】:

    标签: python arrays numpy save


    【解决方案1】:

    现有的子类有什么作用? np.matrixnp.recarraynp.ma.MaskedArray。我没有测试过他们的save 或查看他们是否有特殊代码。 matrix 具有相同的属性和数据缓冲区,只是限制维度的方法。掩码数组同时具有datamask 数组属性。 recarray 就像一个结构化数组,具有不同的索引方法。

    scipy.sparse有自己的保存,它使用savez来保存自己的属性。这也需要它自己的负载,以重新创建矩阵。 sparse 虽然不是子类。

    我以后可能会做一些探索自己。

    但不要对pickle 嗤之以鼻。 np.savepickle 之间有密切的联系。 np.savendarray的pickle方法,而save使用pickle序列化对象元素。

    不保留矩阵子类:

    In [52]: np.save('matrix.npy',M)
    In [53]: np.load('matrix.npy')
    Out[53]: 
    array([[1, 2],
           [3, 4]])
    

    pickle 保留子类(demo 省略)。

    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)
    

    【讨论】:

      猜你喜欢
      • 2018-10-26
      • 1970-01-01
      • 2012-08-02
      • 2015-05-20
      • 1970-01-01
      • 2012-05-13
      • 2012-01-20
      • 1970-01-01
      • 2021-09-13
      相关资源
      最近更新 更多