首页 > 解决方案 > 用将索引作为参数的对象填充 2d numpy 数组

问题描述

想象一下这样的课程。

class Foo:
   def __init__(self,y,x):
      self.y = y
      self.x = x

然后我有一个数组

obj_arr = np.zeros((200,200), dtype=object)

我想用完整的类填充它,但输入参数作为数组的索引。

我玩弄了 np.where 的想法,但看不到如何添加参数。

np.where(obj_arr == None, obj_arr, Foo()) 

目前我正在做这个令人作呕的嵌套循环。1)我知道它不是正确的方法 2)它需要永远。

for y in range(obj_arr.shape[0]):
    for x in range(obj_arr.shape[1]):
        obj_arr[y,x] == Foo(y,x)

在我发疯之前,请有人把我推向正确的方向。

标签: pythonnumpy

解决方案


class Foo:
    def __init__(self, y, x):
        self.y = y
        self.x = x
    def __repr__(self):
        return f'Foo({self.y}, {self.x})'

In [69]: Foo(1,2)
Out[69]: Foo(1, 2)

建议的nditer解决方案:

def foo1(n):
    a = np.empty((n,n), dtype=object)
    with np.nditer(a, flags=['multi_index', 'refs_ok'], op_flags=['writeonly']) as it:
        for x in it:
            x[...] = Foo(it.multi_index[1], it.multi_index[0])
    return a

In [70]: foo1(2)
Out[70]: 
array([[Foo(0, 0), Foo(1, 0)],
       [Foo(0, 1), Foo(1, 1)]], dtype=object)

嵌套循环:

def foo2(n):
    a = np.empty((n,n), dtype=object)
    for i in range(n):
        for j in range(n):
            a[i,j] = Foo(i,j)
    return a

In [71]: foo2(2)
Out[71]: 
array([[Foo(0, 0), Foo(0, 1)],
       [Foo(1, 0), Foo(1, 1)]], dtype=object)

我最喜欢的,frompyfunc

def foo3(n):
    f = np.frompyfunc(Foo, 2, 1)
    I,J = np.meshgrid(np.arange(n),np.arange(n), sparse=True)
    return f(I,J)

In [72]: foo3(2)
Out[72]: 
array([[Foo(0, 0), Foo(1, 0)],
       [Foo(0, 1), Foo(1, 1)]], dtype=object)

时间:

In [73]: timeit foo1(200)
144 ms ± 305 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [74]: timeit foo2(200)
25.7 ms ± 958 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [75]: timeit foo3(200)
17.7 ms ± 40.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

为了比较,嵌套列表:

def foo4(n):
    alist = []
    for i in range(n):
        blist = []
        for j in range(n):
            blist.append(Foo(i,j))
        alist.append(blist)
    return alist

In [77]: foo4(2)
Out[77]: [[Foo(0, 0), Foo(0, 1)], [Foo(1, 0), Foo(1, 1)]]
In [78]: timeit foo4(200)
18.6 ms ± 149 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

推荐阅读