numpy 在列表中查找几乎相等值的列表

ryoqjall  于 2023-11-18  发布在  其他
关注(0)|答案(1)|浏览(125)

我有一个一维numpy数组,我想找到子列表/包含几乎相等的值的子数组。这意味着它们之间的差异不会超过公差。我的意思是在解决方案中有一个中心点,所有其他点的差异都不会超过公差。例如,如果我有[1.0, 2.2, 1.4, 1.8, 1.5, 2.1]和公差0.2,则期望的结果是[[1.4, 1.5], [2.1, 2.2]]。以下是我认为函数可以完成这项工作:

import numpy as np

def find_almost_equal(input, tol):
    sorted = np.sort(input)
    result = []
    for i, v1 in enumerate(sorted):
        result.append([])
        for j, v2 in enumerate(sorted):
            if v2 - tol < v1 < v2 + tol:
                result[i].append(v2)

    result = [r for r in result if len(r) > 1]

    for i, r1 in enumerate(result):
        for j, r2 in enumerate(result):
            if set(r2).issubset(set(r1)):
                del result[j]

    return result

test = np.array([2.6, 1.2, 1.5, 1.8, 2.0, 2.2, 2.5, 1.1, 1.4])
tolerance = 0.15

almost_equal = find_almost_equal(test, tolerance)
print(almost_equal)

字符串
结果是[[1.1, 1.2], [1.4, 1.5], [2.5, 2.6]]。对于tolerance = 0.25,结果是[[1.1, 1.2, 1.4], [1.4, 1.5], [1.8, 2.0, 2.2], [2.5, 2.6]]
当一个点属于几个子列表时,我的算法并不总是给予正确的结果。例如,输入[1.0, 1.1, 1.2, 1.3, 1.4]tolerance = 0.2,输出是[[1.0, 1.1, 1.2], [1.2, 1.3, 1.4]],而预期的结果是[[1.0, 1.1, 1.2], [1.1, 1.2, 1.3], [1.2, 1.3, 1.4]]
问题是:有没有更简单的方法来做到这一点(最好是在numpy中)?我如何才能正确地做到这一点?

egdjgwm8

egdjgwm81#

使用更多的NumPy功能,一种稍微更简洁的方法是制作一个差异数组(如this answer所示),如:

def find_almost_equal(inp, tol):
    # create array of differences
    inpa = np.sort(inp)
    diff = np.abs(np.subtract.outer(inpa, inpa))
    
    # get precision of float type
    prec = np.finfo(inpa.dtype).eps * 10
    
    # loop over rows in diff array (except first and last)
    l = []
    for row in diff[1:-1]:
         # get values within tolerance (accounting for floating point precision)
         r = inpa[row + prec  < tol].tolist()
         if len(r) > 1:
             for i, prev in enumerate(l):
                 # make sure list isn't subset of previous lists
                 if set(r).issubset(prev):
                     break
                 elif set(prev).issubset(r):
                     # add in longer lists
                     del l[i]
                     l.append(r)
                     break
             else:
                 l.append(r)
    return l

字符串
这给出:

find_almost_equal([2.6, 1.2, 1.5, 1.8, 2.0, 2.2, 2.5, 1.1, 1.4], 0.15)
[[1.1, 1.2], [1.4, 1.5], [2.5, 2.6]]
find_almost_equal([2.6, 1.2, 1.5, 1.8, 2.0, 2.2, 2.5, 1.1, 1.4], 0.25)
[[1.1, 1.2, 1.4], [1.2, 1.4, 1.5], [1.8, 2.0, 2.2], [2.5, 2.6]]
find_almost_equal([1.0, 1.1, 1.2, 1.3, 1.4], 0.2)
[[1.0, 1.1, 1.2], [1.1, 1.2, 1.3], [1.2, 1.3, 1.4]]

相关问题