使用NumPy创建n x n的实例数组

3 投票
1 回答
2760 浏览
提问于 2025-04-18 05:49

我正在尝试用NumPy创建一个n乘n的对象数组,但遇到了一些问题。假设数组的维度设置为m=n=3。我想给每个元素分配一个我的类Vector的实例,这个类代表n维向量。

在我第一次尝试时,我试着用以下方式给一个二维向量赋值:

    array_size = 4
    np.array([ 
          [ Vector(1,2) for j in xrange(array_size) ] 
          for i in xrange(array_size) ], dtype=object)

结果不是我想要的Vector实例数组,而是Python返回了:

[[[1 2]
  [1 2]
  [1 2]]

 [[1 2]
  [1 2]
  [1 2]]

 [[1 2]
  [1 2]
  [1 2]]]

上面的结果是一个形状为(3, 3, 2)的数组,而不是(2, 2)。NumPy把Vector实例转换成了第三个数组维度。这不是我想要的,所以我又尝试了另一种方法:

我先定义了一个空的对象数组,然后把实例赋值给它:

    array_size=3
    mx = np.empty([array_size, array_size], dtype=object).astype(list)

    for i in xrange(array_size):
        for j in xrange(array_size):
            mx[i][j] = Vector(1,2)

有趣的是,我必须把这个数组转换成列表。这样做后,它就能很好地工作,返回我需要的结果:

[[< Vector: [1, 2] > < Vector: [1, 2] > < Vector: [1, 2] >]  
 [< Vector: [1, 2] > < Vector: [1, 2] > < Vector: [1, 2] >]  
 [< Vector: [1, 2] > < Vector: [1, 2] > < Vector: [1, 2] >]]

然后可以把这个列表再转换回数组。所以,这个数组可以以我想要的方式存放对象。但是,似乎没有简单的方法来直接赋值这些实例。而且,难道没有更符合Python风格的方法吗?我真的想摆脱这个嵌套循环。

我还尝试了np.nditer

    array_size=3
    mx = np.empty([array_size, array_size], dtype=object)

    for i in np.nditer(mx, flags=["refs_ok"], op_flags=["writeonly"]):
        i[...] = Vector(1, 2)

但这个方法返回了一个错误,而不是数组:

ValueError: assignment to 0-d array

这个错误我不太明白。

有没有人能给我一个关于嵌套循环的好解决方案?对这个值错误的解释也很欢迎。

1 个回答

2

你的循环应该能正常工作,如果你把它转换成列表,并且像这样进行赋值:

        mx[i,j] = Vector(1,2)

在你第一次尝试时,np.array 只是正常工作。它看到了一组可以转换成三维数组的数据,所以就这么做了。

如果你想得到一个包含对象的二维数组,可以把这个:

a = np.array(<nested list of Vectors>, dtype=object)  # Doesn't work as desired.

改成这个:

vectors = <nested list of Vectors>
a = np.empty(<desired shape>, dtype=object)
a[...] = vectors

这里有一个具体的例子:

我没有你的 Vector 类,所以我就用 numpy 数组作为我想放进对象数组里的对象。

这是我想放进对象数组里的数据。它是一个嵌套的 numpy 数组列表,每个数组都有两个元素:

In [26]: vectors = [[np.array([10*j + k, 10*j + k + 1]) for k in range(3)] for j in range(3)]

In [27]: vectors
Out[27]: 
[[array([0, 1]), array([1, 2]), array([2, 3])],
 [array([10, 11]), array([11, 12]), array([12, 13])],
 [array([20, 21]), array([21, 22]), array([22, 23])]]

你可以把 np.array([10*j + k, 10*j + k + 1]) 改成 Vector(10*j + k, 10*j + k + 1),用你的 Vector 类来试试。

a 是我正在创建的对象数组:

In [28]: a = np.empty((3, 3), dtype=object)

像这样把向量赋值给 a

In [29]: a[...] = vectors   # or `a[:,:] = vectors` 

In [30]: a
Out[30]: 
array([[array([0, 1]), array([1, 2]), array([2, 3])],
       [array([10, 11]), array([11, 12]), array([12, 13])],
       [array([20, 21]), array([21, 22]), array([22, 23])]], dtype=object)

In [31]: a.shape
Out[31]: (3, 3)

撰写回答