3

我试图在 ndarray 中找到一个浮点数。由于我使用的软件包(Abaqus),它输出的精度有点低。例如,10 类似于 10.00003。因此,我想知道是否有一种“正确”的方法来做到这一点,它比我的代码更整洁。

示例代码:

import numpy as np

array = np.arange(10)
number = 5.00001

如果我这样做:</p>

idx = np.where(number==array)[0][0]

然后结果为空,因为 5.00001 不等于 5。

现在我在做:

atol = 1e-3 # Absolute tolerance
idx = np.where(abs(number-array) < atol)[0][0]

哪个有效,并且不太混乱......但我想知道会有一种更简洁的方法来做到这一点。谢谢!

PS:numpy.allclose()是另一种方法,但我需要使用number * np.ones([array.shape[0], array.shape[1]])它对我来说仍然很冗长......


编辑:非常感谢大家的精彩回答!np.isclose() 是我正在寻找的确切功能,我错过了它,因为它不在文档中......如果不是你们,我不会在他们更新文档之前意识到这一点。再次感谢你!

4

3 回答 3

5

PS: numpy.allclose() 是另一种方法,但我需要使用 number * np.ones([array.shape[0], array.shape[1]]) ,它对我来说仍然很冗长.. .

你几乎不需要做任何类似的事情number * np.ones([array.shape[0], array.shape[1]])。正如您可以将该标量乘以numberones数组以将其所有1值乘以number,您可以将该标量传递numberallclose以将所有原始数组的值与 进行比较number。例如:

>>> a = np.array([[2.000000000001, 2.0000000002], [2.000000000001, 1.999999999]])
>>> np.allclose(a, 2)
True

附带说明一下,如果您确实需要一个全为 2 的数组,则有一种比将 2 乘以更简单的方法ones

>>> np.tile(2, array.shape)
array([[2, 2], [2, 2]])

就此而言,我不知道您为什么需要这样做[array.shape[0], array.shape[1]]。如果数组是二维的,那与array.shape. 如果数组可能更大,它与array.shape[:2].


我不确定这是否能解决您的实际问题,因为您似乎想知道哪些是接近的,哪些不是接近的,而不仅仅是它们是否都是。但是,如果不是因为创建要与之比较的数组太冗长,您说您可以使用这一事实。allclose

所以,如果你需要whereclose而不是allclose……好吧,没有这样的功能。但是建立自己很容易,如果你反复做,你总是可以把它包起来。

如果你有一个isclose方法——比如allclose,但返回一个 bool 数组而不是一个 bool——你可以写:

idx = np.where(isclose(a, b, 0, atol))[0][0]

……或者,如果你一遍又一遍地这样做:

def whereclose(a, b, rtol=1e-05, atol=1e-08):
    return np.where(isclose(a, b, rtol, atol))

idx = whereclose(a, b, 0, atol)[0][0]

事实证明,numpy 1.7 版确实具有该功能(另请参见此处),但它似乎不在文档中。如果您不想依赖可能未记录的函数,或者需要使用 numpy 1.6,您可以自己编写:

def isclose(a, b, rtol=1e-05, atol=1e-08):
    return np.abs(a-b) <= (atol + rtol * np.abs(b))
于 2013-09-09T19:21:30.573 回答
2

如果您有最新的 numpy (1.7),那么最好的方法是使用np.isclose它将自动一起广播形状:

import numpy as np
a = np.arange(10)
n = 5.000001
np.isclose(a, n).nonzero()
#(array([5]),)

或者,如果您希望只有一场比赛:

np.isclose(a, n).nonzero()[0][0]
#5

np.nonzero基本上是一样的,np.where只是它没有 if 条件 then/else 能力)

于 2013-09-09T21:18:24.633 回答
0

具体来说abs(A - B) < atol,您在上面使用的方法是跨多种语言进行浮点比较的标准方法。显然,当使用 numpyA和/或B可以是数组或数字时。

这是另一种可能有用的方法。我不确定它是否适用于您的情况,但是如果您要在数组中查找多个数字(这是一个常见的用例),它可能会非常有帮助。它的灵感来自这个类似的问题。

import numpy as np

def find_close(a, b, rtol=1e-05, atol=1e-08):
    tol = atol + abs(b) * rtol
    lo = b - tol
    hi = b + tol
    order = a.argsort()
    a_sorted = a[order]
    left = a_sorted.searchsorted(lo)
    right = a_sorted.searchsorted(hi, 'right')
    return [order[L:R] for L, R in zip(left, right)]

a = np.array([2., 3., 3., 4., 0., 1.])
b = np.array([1.01, 3.01, 100.01])
print find_close(a, b, atol=.1)
# [array([5]), array([1, 2]), array([], dtype=int64)]
于 2013-09-09T22:18:26.293 回答