如何匹配两个不等长的numpy数组?

时间:2011-09-12 06:56:43

标签: python numpy

我有两个1D numpy数组。长度不等。我想制作彼此接近的元素对(array1_elemnt,array2_element)。让我们考虑以下示例

    a = [1,2,3,8,20,23]
    b = [1,2,3,5,7,21,35]

预期结果是

    [(1,1), 
    (2,2), 
    (3,3), 
    (8,7),
    (20,21),
    (23,25)]

重要的是要注意5是独自留下的。它可以很容易地通过循环完成,但我有非常大的数组。我考虑过使用最近邻居。但感觉就像用正典杀死一只麻雀。

任何人都可以建议任何优雅的解决方案。

非常感谢。

5 个答案:

答案 0 :(得分:2)

如何使用Needleman-Wunsch算法? :)

得分矩阵将是微不足道的,因为两个数字之间的“距离”只是它们的差异。

但那可能就像用坦克杀死一只麻雀......

答案 1 :(得分:1)

您可以使用内置的map函数来矢量化执行此操作的函数。例如:

ar1 = np.array([1,2,3,8,20,23])
ar2 = np.array([1,2,3,5,7,21,35])
def closest(ar1, ar2, iter):
    x = np.abs(ar1[iter] - ar2)
    index = np.where(x==x.min())
    value = ar2[index]
    return value

def find(x):
    return closest(ar1, ar2, x)
c = np.array(map(find, range(ar1.shape[0])))

在上面的示例中,看起来您希望在配对后排除值。在这种情况下,您可以在第一个函数中包含一个删除过程,但是要非常小心数组1的排序方式:

 def closest(ar1, ar2, iter):
    x = np.abs(ar1[iter] - ar2)
    index = np.where(x==x.min())
    value = ar2[index]
    ar2[ar2==value] = -10000000
    return value

答案 2 :(得分:0)

我能想到的最好的方法是使用循环。如果python中的循环很慢,可以使用Cython加速编码。

答案 3 :(得分:0)

我认为可以这样做:

  1. 创建两个新的结构化数组,使得第二个索引为0或1,表示该值属于哪个数组,即键
  2. 连接两个数组
  3. 沿第一个字段(值)
  4. 对联合数组进行排序
  5. 使用2个堆栈:在左侧堆栈中使用键1来遍历数组放置元素,当使用键0穿过元素时,将它们放在右侧堆栈中。当您使用键0到达第二个元素时,对于第一个键0,检查左右堆栈的顶部和底部并获取最接近的值(可能具有最大距离),切换堆栈并继续。
  6. 排序应该是最慢的步骤,并且堆栈的最大总空间是n或m。

答案 4 :(得分:0)

您可以执行以下操作:

a = np.array([1,2,3,8,20,23])
b = np.array([1,2,3,5,7,21,25])

def find_closest(a, sorted_b):
    j = np.searchsorted(.5*(sorted_b[1:] + sorted_b[:-1]), a, side='right')
    return b[j]

b.sort()  # or, b = np.sort(b), if you don't want to modify b in-place
print np.c_[a, find_closest(a, b)]

# ->
# array([[ 1,  1],
#        [ 2,  2],
#        [ 3,  3],
#        [ 8,  7],
#        [20, 21],
#        [23, 25]])

这应该很快。它的工作原理是searchsorted会在每个数字a找到b之后的两个数字之间的中点,即最接近的数字。