改变不同尺寸的阵列一起广播

时间:2017-01-24 01:33:16

标签: python arrays numpy broadcast dimensions

我正在寻找一种更优化的方法将(n,n)或(n,n,1)矩阵转换为(n,n,3)矩阵。我从(n,n,3)开始,但是在我对第二轴执行求和(n,n)之后,我的尺寸减小了。基本上,我想保持数组的原始大小,并让第二轴重复3次。我需要这个的原因是我稍后会用另一个(n,n,3)数组广播它,但它们需要相同的尺寸。

我当前的方法有效,但看起来并不优雅。

a0=np.random.random((n,n))
b=a.flatten().tolist()
a=np.array(zip(b,b,b))
a.shape=n,n,3

此设置具有所需的结果,但很笨重且难以遵循。有没有办法通过复制第二个索引直接从(n,n)到(n,n,3)?或者也许是一种不开始缩小数组的方法?

2 个答案:

答案 0 :(得分:2)

Nonenp.newaxis是向数组添加维度的常用方法。 ({3})与(3,3,1)同样有效:

reshape

In [64]: arr=np.arange(9).reshape(3,3) In [65]: arr1 = arr[...,None] In [66]: arr1.shape Out[66]: (3, 3, 1) 因为函数或方法会复制它。

repeat

但你可能不需要这样做。广播a(3,3,1)与(3,3,3)。

In [72]: arr2=arr1.repeat(3,axis=2)
In [73]: arr2.shape
Out[73]: (3, 3, 3)
In [74]: arr2[0,0,:]
Out[74]: array([0, 0, 0])

实际上它会用(3,)广播来制作(3,3,3)。

In [75]: (arr1+arr2).shape
Out[75]: (3, 3, 3)

所以In [77]: arr1+np.ones(3,int) Out[77]: array([[[1, 1, 1], [2, 2, 2], ... [[7, 7, 7], [8, 8, 8], [9, 9, 9]]]) 是将(3,3,1)扩展到(3,3,3)的另一种方法。

广播规则是:

arr1+np.zeros(3,int)

广播根据需要在开始时添加尺寸。

在轴上求和时,可以使用参数保持原始维数:

(3,3,1) + (3,) => (3,3,1) + (1,1,3) => (3,3,3)

如果你想沿着任何维度减去数组的平均值,这很方便:

In [78]: arr2.sum(axis=2).shape
Out[78]: (3, 3)
In [79]: arr2.sum(axis=2, keepdims=True).shape
Out[79]: (3, 3, 1)

答案 1 :(得分:1)

您可以先在a上创建一个新轴(轴= 2),然后沿此新轴使用np.repeat

np.repeat(a[:,:,None], 3, axis = 2)

或者另一种方法,展平数组,重复元素然后重塑:

np.repeat(a.ravel(), 3).reshape(n,n,3)

结果比较:

import numpy as np
n = 4
a=np.random.random((n,n))
b=a.flatten().tolist()
a1=np.array(zip(b,b,b))
a1.shape=n,n,3
# a1 is the result from the original method

(np.repeat(a[:,:,None], 3, axis = 2) == a1).all()
# True

(np.repeat(a.ravel(), 3).reshape(4,4,3) == a1).all()
# True

时间安排,使用内置numpy.repeat也会显示加速:

import numpy as np
n = 4
a=np.random.random((n,n))
​
def rep():
    b=a.flatten().tolist()
    a1=np.array(zip(b,b,b))
    a1.shape=n,n,3

%timeit rep()
# 100000 loops, best of 3: 7.11 µs per loop

%timeit np.repeat(a[:,:,None], 3, axis = 2)
# 1000000 loops, best of 3: 1.64 µs per loop

%timeit np.repeat(a.ravel(), 3).reshape(4,4,3)
# 1000000 loops, best of 3: 1.9 µs per loop