如何创建一个2D numpy数组,每个元素都是其索引的元组?

时间:2018-03-07 18:05:57

标签: python arrays numpy

我需要一种方法来制作元组的二维数组,其中每个元组是该位置的一对索引。我需要这个没有for循环,因为我正在使用大矩阵。

例如,3x3案例将是:

array([[(0, 0), (0, 1), (0, 2)],
       [(1, 0), (1, 1), (1, 2)],
       [(2, 0), (2, 1), (2, 2)]], dtype=object)

我知道有numpy.indices并且在网上有一些建议(有一篇帖子询问这个here),但他们的建议基本上给出了一个3D数组。我需要一个2D,所以我可以将它传递给矢量化函数(这一个here)。我需要函数来处理这对索引,如果我将它传递给上面提到的3D版本,每个单独的索引值都会传递给函数,而不是该对。

但如果我的指数作为一个元组成对出现,这种情况就不会发生。尝试使用小型数组,它的工作原理。问题是,除了使用for循环迭代之外,我无法找到获取元组二维数组的方法。尝试过它需要太长时间。但我对编程很陌生,所以也许有人知道另一种方式吗?

2 个答案:

答案 0 :(得分:0)

如果没有关于您需要多大阵列的详细信息,这很难回答。我怀疑nditer可以足够快地执行此操作。答案here引用了您可能有兴趣在c中执行此操作的原因。

如果像

那样的话
import numpy as np
myarray = np.array([[(i, j) for i in range(1000)]
                         for j in range(1000)])

太慢,甚至无法运行它很难想象这里有一个合理的python解决方案

答案 1 :(得分:0)

这是一个元组列表:

In [137]: idx=np.ndindex(3,3)
In [138]: list(idx)
Out[138]: [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

我提到了vectorize signature参数。该版本使用ndindex这样来迭代输入。

尝试从此列表中生成一个数组,得到一个18个元素的数组,可以重新转换为(3,3,2)。但是我们最近讨论了一个技巧(关于制作对象数组),我可以创建一个3x3的元组数组:

In [144]: res = np.empty((3,3),object)
In [145]: for idx in np.ndindex(3,3):
     ...:     res[idx] = idx
     ...:     
In [146]: res
Out[146]: 
array([[(0, 0), (0, 1), (0, 2)],
       [(1, 0), (1, 1), (1, 2)],
       [(2, 0), (2, 1), (2, 2)]], dtype=object)

从相同大小的子列表列表中创建对象dtype数组有点棘手。 np.array尽可能尝试创建基本数字dtype的多维数组。

对于它的价值,迭代列表比在数组上迭代更快。对象dtype数组的迭代速度比数字数据快,因为它已经包含像列表一样的对象指针。

def foo(ij):
    print(ij)
    return 4*ij[0]+ij[1]

使用对象dtype res

In [157]: f1 = np.vectorize(foo)
In [158]: f1(res)
(0, 0)
(0, 0)
(0, 1)
(0, 2)
(1, 0)
(1, 1)
(1, 2)
(2, 0)
(2, 1)
(2, 2)
Out[158]: 
array([[ 0,  1,  2],
       [ 4,  5,  6],
       [ 8,  9, 10]])

使用签名和3d数组我得到同样的东西:

In [159]: f=np.vectorize(foo, signature='(n)->()')
In [160]: 
In [160]: idx=np.ndindex(3,3)
In [161]: arr = np.array(list(idx)).reshape(3,3,2)
In [162]: f(arr)
[0 0]
[0 1]
[0 2]
[1 0]
[1 1]
[1 2]
[2 0]
[2 1]
[2 2]
Out[162]: 
array([[ 0,  1,  2],
       [ 4,  5,  6],
       [ 8,  9, 10]])

但获取此数组的最佳方法是使用全数组操作:

In [164]: 4*arr[:,:,0]+arr[:,:,1]
Out[164]: 
array([[ 0,  1,  2],
       [ 4,  5,  6],
       [ 8,  9, 10]])