使用两个np.linspace,如何用复杂值填充2D数组?

时间:2018-09-30 11:24:03

标签: python python-3.x numpy

我正在尝试用complex(x,y)填充2D数组,其中xy来自两个两个数组:

xstep = np.linspace(xmin, xmax, Nx)
ystep = np.linspace(ymin, ymax, Ny)

但是我不知道如何将这些值“散布”在2D数组上。

到目前为止,我的尝试还没有真正解决。我一直希望以下方面的东西:

result = np.array(xstep + (1j * ystep))

也许来自fromfunctionmeshgridfull的东西,但我不能完全使它生效。

例如,说我这样做:

xstep = np.linspace(0, 1, 2)  # array([0., 1.])
ystep = np.linspace(0, 1, 3)  # array([0. , 0.5, 1. ])

我正在尝试构造一个答案:

array([
[0+0j, 0+0.5j, 0+1j],
[1+0j, 1+0.5j, 1+1j]
])

请注意,我还没有嫁给linspace,所以任何更快的方法都可以,这是我创建Numpy数组的自然起点。

3 个答案:

答案 0 :(得分:2)

In [4]: xstep = np.linspace(0, 1, 2)

In [5]: ystep = np.linspace(0, 1, 3)

In [6]: xstep[:, None] + 1j*ystep
Out[6]: 
array([[0.+0.j , 0.+0.5j, 0.+1.j ],
       [1.+0.j , 1.+0.5j, 1.+1.j ]])

xstep[:, None]等效于xstep[:, np.newaxis],其目的是向右侧的xstep 添加新轴。因此,xstep[:, None]是形状为(2, 1)的二维数组。

In [19]: xstep[:, None].shape
Out[19]: (2, 1)
因此,

xstep[:, None] + 1j*ystep是形状为(2, 1)的2D数组和形状为(3,)的1D数组之和。

NumPy broadcasting通过自动在左侧添加新的轴(长度为1) 来解决这种明显的形状冲突。因此,通过NumPy广播规则,1j*ystep被提升为形状为(1, 3)的数组。 (请注意,xstep[:, None]必须在右侧显式添加新轴,而广播会在左侧自动添加新轴。这就是1j*ystep[None, :]虽有效但不必要的原因。)

广播进一步将两个数组都提升为通用形状(2, 3)(但以内存有效的方式,无需复制数据)。沿长度为1的轴的值被重复广播:

In [15]: X, Y = np.broadcast_arrays(xstep[:, None], 1j*ystep)

In [16]: X
Out[16]: 
array([[0., 0., 0.],
       [1., 1., 1.]])

In [17]: Y
Out[17]: 
array([[0.+0.j , 0.+0.5j, 0.+1.j ],
       [0.+0.j , 0.+0.5j, 0.+1.j ]])

答案 1 :(得分:1)

reshape(-1,1)的{​​{1}}用作:

xstep

答案 2 :(得分:1)

您可以将np.ogrid与虚构的“步骤”一起使用以获得linspace语义:

y, x = np.ogrid[0:1:2j, 0:1:3j]                                                                               
y + 1j*x
# array([[0.+0.j , 0.+0.5j, 0.+1.j ],                                                                                 
#        [1.+0.j , 1.+0.5j, 1.+1.j ]])                                                                                

此处ogrid行表示创建一个开放的2D网格。轴0:0至1,2步,轴1:0至1,3步。切片“步骤”的类型充当开关,如果它是虚构的(实际上是任何复杂类型的对象),则其绝对值将被使用,并且该表达式被视为linspace。否则,将应用范围语义。

返回值

y, x
# (array([[0.],                                                                                                       
#         [1.]]), array([[0. , 0.5, 1. ]]))                                                                                                                                                                                          

“广播准备就绪”,因此在示例中,我们可以简单地将它们添加并获得完整的2D网格。

如果我们在第二个切片中允许我们自己使用一个假想的“停止”参数(仅适用于linspace语义,那么根据您的样式,您可能会希望避免使用此参数)可以将其压缩为一行:

sum(np.ogrid[0:1:2j, 0:1j:3j])
# array([[0.+0.j , 0.+0.5j, 0.+1.j ],
#        [1.+0.j , 1.+0.5j, 1.+1.j ]])

类似但可能更具性能的方法是预先分配,然后广播:

out = np.empty((y.size, x.size), complex)
out.real[...], out.imag[...] = y, x
out
# array([[0.+0.j , 0.+0.5j, 0.+1.j ],
#        [1.+0.j , 1.+0.5j, 1.+1.j ]])

另外一个使用外部总和:

np.add.outer(np.linspace(0,1,2), np.linspace(0,1j,3))
# array([[0.+0.j , 0.+0.5j, 0.+1.j ],
#        [1.+0.j , 1.+0.5j, 1.+1.j ]])