所以我想知道一种执行此计算的Python方式。我有一个全零的2D numpy
数组。现在,根据坐标,我想在其中填充一些值。具体来说,我们有2个整数(a,b)
,然后在数组中用max(abs(index1-a), abs(index2-b))
填充每个位置。
我正在想办法在一行中解决此问题,例如,如果我们想将所有负元素替换为0,那么:
array[array<0] = 0
有关如何单行解决问题的任何提示?我不是在寻找单行循环或lambda表达式。
答案 0 :(得分:1)
使用np.indices
+ np.maximum
:
a, b = 3, 5
i, j = np.indices((10, 7))
np.maximum(np.abs(i - a), np.abs(j - b)))
array([[5, 4, 3, 3, 3, 3, 3],
[5, 4, 3, 2, 2, 2, 2],
[5, 4, 3, 2, 1, 1, 1],
[5, 4, 3, 2, 1, 0, 1],
[5, 4, 3, 2, 1, 1, 1],
[5, 4, 3, 2, 2, 2, 2],
[5, 4, 3, 3, 3, 3, 3],
[5, 4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6, 6]])
np.indices
将行和列索引作为2D矩阵返回;无需重塑。
答案 1 :(得分:0)
我们可以使用以下方法设计:
a = 3 # sample a
b = 5 # sample b
arr = np.zeros((10, 7)) # sample zeros
m, n = arr.shape
arr[:,:] = np.maximum(np.arange(m).reshape(-1,1) - a, np.arange(n) - b)
但是,如果您不需要修改矩阵本身,我们可以简单地构造一个新矩阵(使用arr = np.maximum(..)
)。
对于具有a = 3
和b = 5
的10×7矩阵,我们得到:
>>> arr
array([[-3., -3., -3., -2., -1., 0., 1.],
[-2., -2., -2., -2., -1., 0., 1.],
[-1., -1., -1., -1., -1., 0., 1.],
[ 0., 0., 0., 0., 0., 0., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 2., 2., 2., 2., 2., 2., 2.],
[ 3., 3., 3., 3., 3., 3., 3.],
[ 4., 4., 4., 4., 4., 4., 4.],
[ 5., 5., 5., 5., 5., 5., 5.],
[ 6., 6., 6., 6., 6., 6., 6.]])
编辑:如果要绝对值 np.abs(..)
:
arr[:,:] = np.maximum(np.abs(np.arange(m).reshape(-1,1) - a), np.abs(np.arange(n) - b))
那么结果是:
>>> arr
array([[5, 4, 3, 3, 3, 3, 3],
[5, 4, 3, 2, 2, 2, 2],
[5, 4, 3, 2, 1, 1, 1],
[5, 4, 3, 2, 1, 0, 1],
[5, 4, 3, 2, 1, 1, 1],
[5, 4, 3, 2, 2, 2, 2],
[5, 4, 3, 3, 3, 3, 3],
[5, 4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6, 6]])
性能
我们定义了两个函数f
和g
:
>>> def f():
... a, b = 3, 5
... m, n = 10, 7
... arr = np.zeros((m, n))
... arr[:,:] = np.maximum(np.arange(m).reshape(-1,1) - a, np.arange(n) - b)
...
>>> def g():
... a, b = 3, 5
... m, n = 10, 7
... arr = np.zeros((m, n))
... i, j = np.indices((m, n))
... arr[:,:] = np.maximum(np.abs(i - a), np.abs(j - b))
然后我们同时运行两个函数1'000'000次:
>>> timeit(f, number=1000000)
7.471106000011787
>>> timeit(g, number=1000000)
18.07209299999522
对于1000×700的矩阵,我们也将其运行了1000次:
>>> timeit(f, number=1000)
2.5362389999936568
>>> timeit(g, number=1000)
43.055561000001035
我对这种“性能差距”的假设是np.indices()
创建了一个2×m×n的矩阵,因此分配了相似数量的内存。通过构造两个1d数组,我们在中间矩阵中采用线性时间,并利用广播来计算最终矩阵的元素。