2012-11-26 55 views
0

我有一个给定的值列表和列表集合(列表ABC)具有相似的值。我试图找到一种方法来返回最接近given列表的列表。我想使用最小二乘拟合作为距离度量。因此,在这种情况下Python:按值查找与输入列表值最匹配的列表

given = [0, 1, 2, 3, 4, 5] 
A = [0.1, 0.9, 2, 3.3, 3.6, 5.1] 
B = [-0.1, 0.9, 2.1, 3.1, 3.9, 5] 
C = [0, 1.1, 2, 2.9, 4, 5.1] 

,这将是最接近的配对返回Cgiven

我想我可以纳入类似:

match = [min([val[idx] for val in [A,B,C]], key=lambda x: abs(x-given[idx])) for idx in range(len(given))] 

但是,只返回每个列表元素最接近的值。我不确定如何确定列表C为最接近的逐点匹配。另外,如果列表的长度不同,我真的不知道该怎么做,如果我不按索引比较它们。例如:

given = [0, 1, 2, 3, 4, 5] 
A = [0.1, 0.9, 2, 3.3, 3.6, 2, 5.1, 3, 6.8, 7.1, 8.2, 9] 
B = [-0.1, 0.9, 2.1, 3.1, 3.9] 
C = [-1.7, -1, 0, 1.1, 2, 2.9, 4, 5.1, 6, 7.1, 8] 

仍然会返回C是最接近的配对。

我也使用Numpy,但没有发现任何有用的东西。任何帮助将不胜感激!

+4

我认为你应该从形式化所需的距离度量开始。换句话说,它究竟是什么*使得'given'接近'C'而不是'A'或'B'?没有这个,这个问题太模糊,无法回答。 – NPE

+0

在SO上看到这个问题:http://stackoverflow.com/questions/9365184/computing-similarity-between-two-lists – syrion

+0

@NPE是正确的。我同意,应该选择一些距离度量。 – crow16384

回答

1

您可以使用误差平方的总和。我做了一个快速的例子:

from copy import copy 

def squaredError(a, b): 
    r = copy(a) 

    for i in range(len(a)): 
     r[i] -= b[i] 
     r[i] *= r[i] 

    return sum(r) 

given = [0, 1, 2, 3, 4, 5] 
A = [0.1, 0.9, 2, 3.3, 3.6, 5.1] 
B = [-0.1, 0.9, 2.1, 3.1, 3.9, 5] 
C = [0, 1.1, 2, 2.9, 4, 5.1] 

print squaredError(given, A) 
print squaredError(given, B) 
print squaredError(given, C) 

match = min(map(lambda x: (squaredError(given, x), x), [A,B,C]))[1] 
print match 
+0

完美!这适用于不同长度的列表。非常感谢! –

+0

不客气。来自德国的问候。 – Fred

1

纯粹的python解决方案并不是最高效的,但这里有一个使用最小二乘法实现距离度量的实现。

def distance(x,y): 
    return sum((a-b)**2 for a,b in zip(x,y)) 

given = [0, 1, 2, 3, 4, 5] 
A = [0.1, 0.9, 2, 3.3, 3.6, 5.1] 
B = [-0.1, 0.9, 2.1, 3.1, 3.9, 5] 
C = [0, 1.1, 2, 2.9, 4, 5.1] 

min((A,B,C),key=lambda x:distance(x,given)) 

假设同样大小的np.ndarraysdistance可以写成:

def distance(x,y): 
    return ((x-y)**2).sum() 
+0

@JoeFlip - 是的。它从列表的开头开始。我真的不知道你想如何处理长度不等的序列,但'itertools.izip_longest' *可能对这种情况有用(而不是我上面的'zip')。 – mgilson