【问题标题】:Numpy ndarray subclass - forcing reshape in __array_finalize__Numpy ndarray 子类 - 在 __array_finalize__ 中强制重塑
【发布时间】:2013-02-04 15:40:00
【问题描述】:

我遇到以下问题:

我想编写一个 ndarray 子类并为该子类的任何新实例强制执行形状 (-1,3),无论它采用哪种方式 - 显式构造函数、视图转换或来自模板。

我已经尝试了很多东西,但似乎都没有奏效。 我认为我还没有完全掌握基本过程。非常感谢任何帮助!

import numpy as np

class test(np.ndarray):
def __new__(cls, *args, **kwargs):
    return np.ndarray.__new__(cls, *args, **kwargs)

def __array_finalize__(self, obj):

#        self.resize(-1,3)
#        self.reshape(-1,3)
#        self=self.reshape(-1,3)
        np.reshape(self,(-1,3))

a=np.array([1,2,3])
b=a.view(test)
c=test(a)
d=a.reshape(-1,3)
print '+++++++'
print a.shape,a
print '+++++++'
print b.shape,b
print '+++++++'
print c.shape,c
print '+++++++'
print d.shape,d

澄清我要做什么:

我有我想将其一般视为 3D 的矢量场,因此 (:,3) 形状和 (-1,3) 形状调整大小。我正在寻找一个纯粹的面向对象的解决方案来实现一些额外的方法来补充 NumPy 已经提供的功能。

例如,我已经开始纯粹使用 ndarrays 编写一些东西,但是如果我可以编写代码会更易读

normalizedVector = ndarray.view(my3DVectorClass).normalize()

而不是

normalizedVector = ndarray / ( sum(ndarray**2, axis=1)**0.5 )

我的第二个问题:

  • 我希望不必担心我是否要求形状 (3,) 或 (:,3) 数组的规范化版本。
  • 我希望能够在类方法实现中使用纯线性代数术语,而不必为方法定义中的索引和错误/维度检查而烦恼

我想您可能会争辩说只使用 my3DVectorClass 的实例,但是在使用所有 SciPy 机器时我必须进行反向视图转换,因为如果我没记错的话,他们期望 ndarray,这会使这些部分代码有点臃肿。

如果我的逻辑可能以某种方式出错,我非常感谢您的建议。我仍然处于 OOP 和 SciPy/NumPy 的学习曲线上。

非常感谢!

马库斯

【问题讨论】:

  • 你需要__array_wrap__

标签: python numpy subclass multidimensional-array


【解决方案1】:

您应该看看matrix class 是如何实现的。它使用类似的技巧来维护ndims=2

但是,我和许多其他人认为这种诡计更麻烦,而不值得。 matrix 类在过去引起了很多问题,因为它只是部分表现得像普通的ndarray。考虑改为编写函数。您在上面给出的代码示例将是最易读的,如下所示:normalizedVector = normalize(ndarray)。创建更多子类并不总是最好的设计,即使使用面向对象的样式也是如此。

【讨论】:

  • 嗨罗伯特,确实不是我希望听到的,但你是正确的。最终,函数是直接的解决方案。感谢您的建议!
【解决方案2】:

reshape 将尝试使用新形状创建数据视图,如果不能,它将使用新形状创建数据的副本。但是原始对象保持不变。要就地修改形状,您可以执行以下操作:

self.shape = (-1, 3)

例如:

>>> a = np.arange(9)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8])
>>> np.reshape(a, (-1, 3)) # creates a view with the new shape
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> a # but the original object is unchanged
array([0, 1, 2, 3, 4, 5, 6, 7, 8])
>>> a.shape = (-1, 3) # this modifies the original object
>>> a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

但你必须小心,因为如果不复制就无法重塑它,它会引发AttributeError

>>> a = np.arange(36).reshape(6, 6).T
>>> b = np.reshape(a, (-1, 3)) # creates a copy of the data in a
>>> a.shape = (-1, 3) # tries to reshape in-place, and fails
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: incompatible shape for a non-contiguous array

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多