构建2D金字塔形数组 - Python / NumPy

7

我已经苦思冥想了一段时间,试图以向量化的方式创建此数组,但未能成功。

我需要一个函数,该函数接受2d数组大小n并生成一个大小为(n,n)的2d数组,看起来像这样:

n = 6

np.array([[0,0,0,0,0,0],
          [0,1,1,1,1,0],
          [0,1,2,2,1,0],
          [0,1,2,2,1,0],
          [0,1,1,1,1,0],
          [0,0,0,0,0,0],

(并且可以接受奇数个参数)

非常感谢任何建议!


什么是非向量化的方式? - roganjosh
2个回答

10

方法 #1

我们可以使用broadcasting技术 -

def pyramid(n):
    r = np.arange(n)
    d = np.minimum(r,r[::-1])
    return np.minimum.outer(d,d)

方法2

我们还可以使用连接来创建d,就像这样 -

d = np.r_[np.arange(n//2),np.arange(n//2-(n%2==0),-1,-1)]

因此,给我们一个替代的一行代码 -

np.minimum.outer(*(2*[np.r_[np.arange(n//2),np.arange(n//2-(n%2==0),-1,-1)]]))

样例运行 -

In [83]: pyramid(5)
Out[83]: 
array([[0, 0, 0, 0, 0],
       [0, 1, 1, 1, 0],
       [0, 1, 2, 1, 0],
       [0, 1, 1, 1, 0],
       [0, 0, 0, 0, 0]])

In [84]: pyramid(6)
Out[84]: 
array([[0, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 1, 0],
       [0, 1, 2, 2, 1, 0],
       [0, 1, 2, 2, 1, 0],
       [0, 1, 1, 1, 1, 0],
       [0, 0, 0, 0, 0, 0]])

In [85]: pyramid(8)
Out[85]: 
array([[0, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 1, 1, 1, 0],
       [0, 1, 2, 2, 2, 2, 1, 0],
       [0, 1, 2, 3, 3, 2, 1, 0],
       [0, 1, 2, 3, 3, 2, 1, 0],
       [0, 1, 2, 2, 2, 2, 1, 0],
       [0, 1, 1, 1, 1, 1, 1, 0],
       [0, 0, 0, 0, 0, 0, 0, 0]])

1
这里很好地运用了 np.minimum.outer,这是一个相当巧妙的解决方案。 - yatu
2
我的天啊,这太聪明了。 - Right leg

2
使用 numpy.pad
import numpy as np

def pyramid(n):
    if n % 2:
        arr = np.zeros((1,1))
        N = int((n-1)/2)
    else:
        arr = np.zeros((2,2))
        N = int(n/2)-1

    for i in range(N):
        arr += 1
        arr = np.pad(arr, 1, mode='constant')
    return arr

输出:

pyramid(6)
array([[0., 0., 0., 0., 0., 0.],
       [0., 1., 1., 1., 1., 0.],
       [0., 1., 2., 2., 1., 0.],
       [0., 1., 2., 2., 1., 0.],
       [0., 1., 1., 1., 1., 0.],
       [0., 0., 0., 0., 0., 0.]])

pyramid(5)
array([[0., 0., 0., 0., 0.],
       [0., 1., 1., 1., 0.],
       [0., 1., 2., 1., 0.],
       [0., 1., 1., 1., 0.],
       [0., 0., 0., 0., 0.]])

numpy.pad(arr, 1, 'constant') 将返回在 arr 周围包裹了一层零的数组。

注:Original Answer 翻译成“最初的回答”。

虽然我喜欢这种方法,但从时间角度来看它似乎相当低效(np.pad必须创建一个新数组,带有内存分配和固有的时间开销),而且关于内存方面,我预见到arr = np.pad(arr)会导致arr及其填充副本在同一时刻共存,从而导致RAM峰值。我认为事先创建一个正确形状的数组,然后再填充它会更加高效。不过,对于这种方法,我还是点个赞,有点函数式的感觉。 - Right leg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接