为什么np.where&np.min似乎不能正常使用这个数组?

Chr*_*neB 1 python arrays numpy minimum where

问题

所以我导入的数组包含从~0.0到~0.76的值.当我开始尝试使用Numpy找到最小值和最大值时,我遇到了一些奇怪的不一致,如果他们是我的错,我想知道如何解决,或者避免如果他们在Numpy开发人员端编程错误.

代码

让我们从使用np.max&找到最大值的位置开始np.where.

print array.shape
print np.max(array)
print np.where(array == 0.763728955743)
print np.where(array == np.max(array))
print array[35,57]
Run Code Online (Sandbox Code Playgroud)

输出是这样的:

(74, 145)
0.763728955743
(array([], dtype=int64), array([], dtype=int64))
(array([35]), array([57]))
0.763728955743
Run Code Online (Sandbox Code Playgroud)

当我查找数组恰好等于最大条目值的位置时,Numpy找不到它.但是,当我只是搜索最大值的位置而不指定该值是什么时,它就可以工作.请注意,这不会发生在np.min.

现在我对minima有一个不同的问题.

print array.shape
print np.min(array)
print np.where(array == 0.0)
print np.where(array == np.min(array))
print array[10,25], array[31,131]
Run Code Online (Sandbox Code Playgroud)

看看回报.

(74, 145)
0.0
(array([10, 25]), array([ 31, 131]))
(array([10, 25]), array([ 31, 131]))
0.0769331747301 1.54220192172e-09
Run Code Online (Sandbox Code Playgroud)

1.54 ^ -9足够接近0.0,看起来它似乎是最小值.但为什么值为0.077的位置也列出np.where?与其他值相比,这甚至不接近0.0.

问题

为什么np.where在输入数组的最大值时似乎不起作用,但在搜索时却是这样np.max(array)?为什么np.where()混合np.min()返回两个位置,其中一个绝对不是最小值?

Mad*_*ist 5

你有两个问题:floats的解释和结果的解释np.where.

  1. 非整数浮点数以二进制形式存储在内部,并不能始终以十进制表示法精确表示.同样,十进制数也不能总是用二进制表示.这就是为什么np.where(array == 0.763728955743)返回一个空数组,而print np.where(array == np.max(array))做正确的事情.请注意,第二种情况只是在内部使用完全二进制数而没有任何转换.搜索最小成功因为0.0 可以用十进制和二进制表示.一般而言,出于此原因和相关原因对floats进行比较是一个坏主意==.
  2. 对于np.where您正在使用的版本,它会转换为np.nonzero.您正在解释结果,因为它为数组的每个维度返回一个数组,而不是单个坐标数组.有很多方式可以这样说:

    • 如果你有三个匹配,你会得到两个数组,每个数组有三个元素.
    • 如果你有一个带有两个匹配的3D输入数组,你会得到三个数组,每个数组都有两个元素.
    • 第一个数组是行坐标(dim 0),第二个数组是列坐标(dim 1).
    • 请注意您是如何解释where最大情况的输出.这是正确的,但它不是你在最小的情况下做的.

有许多方法可以解决这些问题.最简单的可能是使用np.argmaxnp.argmin.这些将分别返回数组中最大值或最小值的第一个坐标.

>>> x = np.argmax(array)
>>> print(x)
array([35, 57])
>> print(array[x])
0.763728955743
Run Code Online (Sandbox Code Playgroud)

这里唯一可能的问题是您可能想要获得所有坐标.

在那种情况下,使用where,或者nonzero很好.与您的代码唯一的区别是您应该打印

print array[10,31], array[25,131]
Run Code Online (Sandbox Code Playgroud)

而不是你正在做的转置值.