Python 使用两个np.linspace,如何用复杂值填充二维数组?

Python 使用两个np.linspace,如何用复杂值填充二维数组?,python,python-3.x,numpy,Python,Python 3.x,Numpy,我试图用复数(x,y)填充二维数组,其中x和y来自两个数组: xstep = np.linspace(xmin, xmax, Nx) ystep = np.linspace(ymin, ymax, Ny) 但是,我不知道如何在2D数组上“分散”这些值 到目前为止,我的尝试并没有真正奏效。我希望有一些类似的东西: result = np.array(xstep + (1j * ystep)) 可能是来自fromfunction、meshgrid或full的内容,但我不能完全让它工作 例如,假设

我试图用
复数(x,y)
填充二维数组,其中
x
y
来自两个数组:

xstep = np.linspace(xmin, xmax, Nx)
ystep = np.linspace(ymin, ymax, Ny)
但是,我不知道如何在2D数组上“分散”这些值

到目前为止,我的尝试并没有真正奏效。我希望有一些类似的东西:

result = np.array(xstep + (1j * ystep))
可能是来自
fromfunction
meshgrid
full
的内容,但我不能完全让它工作

例如,假设我这样做:

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来说是新的。

使用
重塑(-1,1)
对于
xstep
,如下所示:

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

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

result

array([[0.+0.j , 0.+0.5j, 0.+1.j ],
       [1.+0.j , 1.+0.5j, 1.+1.j ]])
xstep
使用
重塑(-1,1)
,如下所示:

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

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

result

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)

因此,
xstep[:,None]+1j*ystep
是二维形状数组
(2,1)
和一维形状数组
(3,)
的总和

通过在左侧自动添加新轴(长度为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 ]])

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

因此,
xstep[:,None]+1j*ystep
是二维形状数组
(2,1)
和一维形状数组
(3,)
的总和

通过在左侧自动添加新轴(长度为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 ]])

您可以将
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
线意味着创建一个开放的二维网格。轴0:0到1,2步,轴1:0到1,3步。切片“step”的类型充当开关,如果它是虚构的(实际上是复杂类型的任何东西),则取其绝对值,并将表达式视为linspace。否则将应用范围语义

返回值

y, x
# (array([[0.],                                                                                                       
#         [1.]]), array([[0. , 0.5, 1. ]]))                                                                                                                                                                                          
是“广播就绪”,因此在示例中,我们可以简单地添加它们并获得完整的2D网格

如果我们在第二个片段中允许自己使用一个虚构的“stop”参数(该参数仅适用于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 ]])

您可以将
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
线意味着创建一个开放的二维网格。轴0:0到1,2步,轴1:0到1,3步。切片“step”的类型充当开关,如果它是虚构的(实际上是复杂类型的任何东西),则取其绝对值,并将表达式视为linspace。否则将应用范围语义

返回值

y, x
# (array([[0.],                                                                                                       
#         [1.]]), array([[0. , 0.5, 1. ]]))                                                                                                                                                                                          
是“广播就绪”,因此在示例中,我们可以简单地添加它们并获得完整的2D网格

如果我们在第二个片段中允许自己使用一个虚构的“stop”参数(该参数仅适用于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 ]])