当前位置: 首页 > 面试题库 >

根据另一个参考数组从一个数组中选择接近匹配

西门马鲁
2023-03-14
问题内容

我有一个数组A和一个引用数组B。的大小A至少等于B。例如

A = [2,100,300,793,1300,1500,1810,2400]
B = [4,305,789,1234,1890]

B实际上是在指定时间信号中A的峰值位置,并且包含稍后时间的峰值位置。但是某些元素A实际上是不是我想要的峰(可能是由于噪声等),我想找到“真正的”一个A基础B。中的“真实”元素AB与中的元素接近,在上面给出的示例中,中的“真实”元素A应为A'=[2,300,793,1300,1810]。在这个例子中应该很明显100,1500,2400不是我们想要的,因为它们与B中的任何元素都相去甚远。如何在python
/ matlab中以最有效/准确的方式对此进行编码?


问题答案:

方法#1: 使用NumPy broadcasting,我们可以在输入数组之间寻找按元素进行的绝对减法,并使用适当的阈值从中过滤掉不需要的元素A。对于给定的样本输入,似乎是一个工作阈值90

因此,我们将有一个实现,像这样-

thresh = 90
Aout = A[(np.abs(A[:,None] - B) < thresh).any(1)]

样品运行-

In [69]: A
Out[69]: array([   2,  100,  300,  793, 1300, 1500, 1810, 2400])

In [70]: B
Out[70]: array([   4,  305,  789, 1234, 1890])

In [71]: A[(np.abs(A[:,None] - B) < 90).any(1)]
Out[71]: array([   2,  300,  793, 1300, 1810])

方法2:thispost在的基础上,这是一种使用的内存有效方法np.searchsorted,这对于大型阵列可能至关重要-

def searchsorted_filter(a, b, thresh):
    choices = np.sort(b) # if b is already sorted, skip it
    lidx = np.searchsorted(choices, a, 'left').clip(max=choices.size-1)
    ridx = (np.searchsorted(choices, a, 'right')-1).clip(min=0)
    cl = np.take(choices,lidx) # Or choices[lidx]
    cr = np.take(choices,ridx) # Or choices[ridx]
    return a[np.minimum(np.abs(a - cl), np.abs(a - cr)) < thresh]

样品运行-

In [95]: searchsorted_filter(A,B, thresh = 90)
Out[95]: array([   2,  300,  793, 1300, 1810])

运行时测试

In [104]: A = np.sort(np.random.randint(0,100000,(1000)))

In [105]: B = np.sort(np.random.randint(0,100000,(400)))

In [106]: out1 = A[(np.abs(A[:,None] - B) < 10).any(1)]

In [107]: out2 = searchsorted_filter(A,B, thresh = 10)

In [108]: np.allclose(out1, out2)  # Verify results
Out[108]: True

In [109]: %timeit A[(np.abs(A[:,None] - B) < 10).any(1)]
100 loops, best of 3: 2.74 ms per loop

In [110]: %timeit searchsorted_filter(A,B, thresh = 10)
10000 loops, best of 3: 85.3 µs per loop

2018年1月更新,进一步提升了性能

我们可以np.searchsorted(..., 'right')通过利用从中获得的索引np.searchsorted(..., 'left')以及absolute计算来避免二次使用,就像这样-

def searchsorted_filter_v2(a, b, thresh):
    N = len(b)

    choices = np.sort(b) # if b is already sorted, skip it

    l = np.searchsorted(choices, a, 'left')
    l_invalid_mask = l==N
    l[l_invalid_mask] = N-1
    left_offset = choices[l]-a
    left_offset[l_invalid_mask] *= -1

    r = (l - (left_offset!=0))
    r_invalid_mask = r<0
    r[r_invalid_mask] = 0
    r += l_invalid_mask
    right_offset = a-choices[r]
    right_offset[r_invalid_mask] *= -1

    out = a[(left_offset < thresh) | (right_offset < thresh)]
    return out

更新了计时以测试进一步的加速-

In [388]: np.random.seed(0)
     ...: A = np.random.randint(0,1000000,(100000))
     ...: B = np.unique(np.random.randint(0,1000000,(40000)))
     ...: np.random.shuffle(B)
     ...: thresh = 10
     ...: 
     ...: out1 = searchsorted_filter(A, B, thresh)
     ...: out2 = searchsorted_filter_v2(A, B, thresh)
     ...: print np.allclose(out1, out2)
True

In [389]: %timeit searchsorted_filter(A, B, thresh)
10 loops, best of 3: 24.2 ms per loop

In [390]: %timeit searchsorted_filter_v2(A, B, thresh)
100 loops, best of 3: 13.9 ms per loop

深层发掘 -

In [396]: a = A; b = B

In [397]: N = len(b)
     ...: 
     ...: choices = np.sort(b) # if b is already sorted, skip it
     ...: 
     ...: l = np.searchsorted(choices, a, 'left')

In [398]: %timeit np.sort(B)
100 loops, best of 3: 2 ms per loop

In [399]: %timeit np.searchsorted(choices, a, 'left')
100 loops, best of 3: 10.3 ms per loop

似乎searchsortedsort占用了几乎所有的运行时,并且它们似乎对于此方法至关重要。因此,采用这种基于排序的方法似乎无法进一步改善它。



 类似资料:
  • 我如何排序一个数组尽可能接近一个目标数组。 例如: 数组最多只能包含4个元素: 但在不是的情况下,排序应如下所示: 排序为 排序为 标准是使它尽可能接近,并且在不存在特定元素的地方,跳过它。 我当前的代码似乎做得不对,我把它包含在下面: null null 我怎么修好它?

  • 问题内容: 我有一个模块(db.py),它从不同的数据库类型(sqlite,mysql等)加载数据。该模块包含一个db_loader类和从其继承的子类(sqlite_loader,mysql_loader)。 使用的数据库类型在单独的params文件中, 用户如何找回正确的物体? 即我该怎么做: 我是在db.py模块中使用一种称为loader的方法,还是有一种更优雅的方式使类可以根据参数选择自己的

  • 假设我有一个spark数据帧,有几列(其中列)和数据帧,有两列:和。 是否有复制以下命令的方法

  • 问题内容: 我有一个看起来像这样的数组。这是一个二维数组。 我想使用此信息来创建一个新的三维数组,如下所示。 请对此有任何帮助。我陷入困境,需要弄清楚如何使用此原始数组创建新数组。因此,基本上,我将每台计算机上的所有作业分组在一起,而这些作业的密钥取决于它们在原始阵列中的状态。因此,如果原始阵列上有一个键为2的作业,而该机上没有其他作业具有更高的键,则它将变成该作业的键0,并使用该机器名创建一个新

  • 问题内容: 我有两个numpy数组A和B。A包含唯一值,而B是A的子数组。 例如: 问题答案: 您可以使用带有- 如果您关心维护订单,也可以使用- 对于一般情况,当&是未排序的数组时,您可以在中引入选项,就像这样- 为了解决一般情况,我还会添加我最喜欢的内容- 样品运行-