Numpy`where`子句的奇怪行为

时间:2018-11-15 05:04:48

标签: numpy pythonanywhere numpy-broadcasting

我看到ufunc where的{​​{1}}子句有奇怪的行为。

Numpy 1.15.3

ADD1

似乎我只能使用In [1]: import numpy as np In [2]: x = np.array([[1,2],[3,4]]) In [3]: y = np.ones(x.shape) * 2 In [4]: print(x, "\n", y) [[1 2] [3 4]] [[2. 2.] [2. 2.]] In [5]: np.add(x, y, where=x==3) Out[5]: array([[2., 2.], #<=========== where do these 2s come from??? [5., 2.]]) In [6]: np.add(x, y, where=x==3, out=np.zeros(x.shape)) Out[6]: array([[0., 0.], [5., 0.]]) In [7]: np.add(x, y, where=x==3, out=np.ones(x.shape)) Out[7]: array([[1., 1.], [5., 1.]]) In [8]: np.add(x, y, where=x==3) Out[8]: array([[1., 1.], # <========= it seems these 1s are remembered from last computation. [5., 1.]]) 参数来获得合理的结果。

以下没有out参数:

out

这会产生一个荒谬的图像:

enter image description here

如果我按如下所示添加import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D fig = plt.figure() ax = fig.add_subplot(111, projection='3d') x = np.linspace(-2,2,60) y = np.linspace(-2,2,60) xx, yy = np.meshgrid(x,y) r= np.ones((60,60), dtype=float) * 2 z = np.sqrt(r**2 - xx**2 - yy**2, where=(r**2 - xx**2 - yy**2)>=0) # <==== HERE!! surf = ax.plot_surface(xx, yy, z, cmap="viridis") 参数,则一切正常。

out

enter image description here

1 个答案:

答案 0 :(得分:3)

由于使用where,您最终在输出中得到了垃圾数据。如您所说,解决方法是初始化自己的输出并将其传递给out

来自docs about the out arg

  

如果'out'为None(默认值),则会创建一个未初始化的返回数组。然后,在广播“ where”为True的地方,用ufunc的结果填充输出数组。如果“ where”是标量True(默认值),则它对应于要填充的整个输出。请注意,未明确填充的输出将保留其未初始化的值。

因此,您跳过的out的值(即whereFalse的索引)将保留之前的值。这就是为什么numpy会“保留”先前计算的值,例如第一个示例代码块末尾的1

正如@WarrenWeckesser在其评论中指出的那样,这也意味着至少在某些情况下,out留为空白时,将同一存储块重新用于输出。有趣的是,您可以通过将每个输出分配给变量来更改获得的结果:

x = np.array([[1,2],[3,4]])
y = np.ones(x.shape) * 2

arr0 = np.add(x, y, where=x==3)
arr1 = np.add(x, y, where=x==3, out=np.zeros(x.shape))
arr2 = np.add(x, y, where=x==3, out=np.ones(x.shape))
arr3 = np.add(x, y, where=x==3)
print(arr3)

现在您可以清楚地在输出中看到垃圾数据:

[[-2.68156159e+154 -2.68156159e+154]
 [ 5.00000000e+000  2.82470645e-309]]