为啥 np.where & np.min 似乎不适用于这个数组?

Posted

技术标签:

【中文标题】为啥 np.where & np.min 似乎不适用于这个数组?【英文标题】:Why don't np.where & np.min seem to work right with this array?为什么 np.where & np.min 似乎不适用于这个数组? 【发布时间】:2017-04-24 01:32:09 【问题描述】:

问题

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

代码

让我们从使用np.maxnp.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]

输出是这样的:

(74, 145)
0.763728955743
(array([], dtype=int64), array([], dtype=int64))
(array([35]), array([57]))
0.763728955743

当我查找数组与最大条目的值完全相等的位置时,Numpy 没有找到它。但是,当我只是搜索最大值的位置而不指定该值是什么时,它会起作用。请注意,np.min 不会发生这种情况。

现在我有一个关于最小值的不同问题。

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]

看看回报。

(74, 145)
0.0
(array([10, 25]), array([ 31, 131]))
(array([10, 25]), array([ 31, 131]))
0.0769331747301 1.54220192172e-09

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

问题

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

【问题讨论】:

可能是 - ***.com/questions/40939626/… Numpy 在打印值时可能会选择将1.54e-9 表示为0,但这并不意味着1.54e-9 等于 0...也许尝试打印repr(np.min(array))? np.max(array) - 0.763728955743 的值是多少?大概不是零 @Eric,它是 -3.00426350464e-13,基本上为零。 至于您的最小值问题,您正在查看错误的单元格。你想要array[10, 31]array[25, 131],而不是array[10, 25]array[31, 131]。 (另外,我建议不要调用你的数组array。) 【参考方案1】:

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

    非整数浮点数在内部以二进制形式存储,不能始终以十进制表示法精确表示。同样,十进制数也不能总是用二进制精确表示。这就是为什么np.where(array == 0.763728955743) 返回一个空数组,而print np.where(array == np.max(array)) 做正确的事情。请注意,第二种情况仅在内部使用确切的二进制数而无需任何转换。搜索最小值成功,因为0.0 可以精确地用十进制和二进制表示。一般来说,出于这个原因和相关原因,比较 floats 和 == 是个坏主意。

    对于您正在使用的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

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

在这种情况下,使用wherenonzero 就可以了。与您的代码的唯一区别是您应该打印

print array[10,31], array[25,131]

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

【讨论】:

【参考方案2】:

尝试使用numpy.isclose() 而不是==。因为无法测试浮点数是否完全相等。

即改变这个:np.where(array == 0.763728955743) 至:np.isclose(array, 0.763728955743)

np.min()np.max() 按预期工作。另请注意,如果您愿意,可以提供像 arr.min(axis=1) 这样的轴。

如果这不能解决问题,也许您可​​以在某处发布一些 csv 数据以尝试重现问题?我有点怀疑这是 numpy 本身的错误,但你永远不知道!

【讨论】:

哎呀,Mad Physicist 的回答比我的详细多了:) isclose 在这种情况下不适用,因为您需要实际最大/最小值的坐标,而不仅仅是靠近它们的任何坐标。 是的,但是 isclose() 的默认容差非常小。 您不知道数组中的增量是什么。如果增量为 ~1eps,那么您基本上使用的是==。如果它们更大,它们可能会使您的测试无效。

以上是关于为啥 np.where & np.min 似乎不适用于这个数组?的主要内容,如果未能解决你的问题,请参考以下文章

聚类--K均值算法:自主实现与sklearn.cluster.KMeans调用

当 np.where 抛出 TypeError 时,为啥 np.vectorize 在这里工作?

numpy的花式操作

如何反转 numpy.where (np.where) 函数

熊猫相当于 np.where

使用 np.where 在二维数组中查找匹配行