如何计算两个二维数组的曼哈顿距离(或 L1/cityblock)?
how to calculate Manhattan distance (or L1/ cityblock) for two 2D array?
对于一维 vector/array 它更容易。例如:
array1 = [1, 2, 3]
array2 = [1, 1, 1]
曼哈顿距离为:(0+1+2) 即 3
import numpy as np
def cityblock_distance(A, B):
result = np.sum([abs(a - b) for (a, b) in zip(A, B)])
return result
2 个点的输出将是:3
但是 2D array/vector 呢?例如,两个二维向量的曼哈顿(或 L1 或城市街区)将是什么(如下):
arr1 = [[29, 30, 36, 30, 18],[37, 37, 49, 54, 23]]
arr2 = [[31, 33, 37, 34, 22],[37, 38, 50, 58, 26]]
如果我使用上面提到的代码,它会给出 3 作为 1 D 向量的输出。对于 2D 向量,输出显示为 2281。在我看来,逻辑曼哈顿距离应该是这样的:
difference of the first item between two arrays: 2,3,1,4,4 which sums to 14
difference of the second item between two array:0,1,1,4,3 which is 9.
总和为 23,因此这两个二维数组之间的曼哈顿距离为 23。
是我计算有误还是我的L1距离概念有问题?
您可以修改您的代码以通过依次比较二维数组中的每个列表(使用您的一维案例代码)然后对结果求和来计算所需的结果:
def cityblock_distance(A, B):
result = np.sum([np.sum([abs(a - b) for (a, b) in zip(C, D)]) for C, D in zip(A, B)])
return result
cityblock_distance(arr1,arr2)
输出:
23
如果 arr1
和 arr2
是 numpy 数组,您可以使用:
# skip if already numpy arrays:
arr1 = np.array(arr1)
arr2 = np.array(arr2)
x = np.sum(np.abs(arr1 - arr2))
print(x)
打印:
23
您编写的代码将无法运行,即使在修复缩进后也是如此:
In [177]:
...: def cityblock_distance(A, B):
...: result = np.sum([abs(a - b) for (a, b) in zip(A, B)])
...: return result
...:
In [178]: arr1=[[29, 30, 36, 30, 18],[37, 37, 49, 54, 23]]; arr2=[[31, 3
...: 3, 37, 34, 22],[37, 38, 50, 58, 26]]
In [179]: cityblock_distance(arr1, arr2)
------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-179-d1b44e49141d> in <module>
----> 1 cityblock_distance(arr1, arr2)
<ipython-input-177-907001cbfc9b> in cityblock_distance(A, B)
1 def cityblock_distance(A, B):
----> 2 result = np.sum([abs(a - b) for (a, b) in zip(A, B)])
3 return result
<ipython-input-177-907001cbfc9b> in <listcomp>(.0)
1 def cityblock_distance(A, B):
----> 2 result = np.sum([abs(a - b) for (a, b) in zip(A, B)])
3 return result
TypeError: unsupported operand type(s) for -: 'list' and 'list'
如果转换为数组,您将获得所需的 L1 范数:
In [180]: cityblock_distance(np.array(arr1), np.array(arr2))
Out[180]: 23
但是,因为默认情况下 numpy.sum
对数组中的所有元素求和,所以您可以完全省略列表理解:
In [181]: np.sum(abs(np.array(arr1)-np.array(arr2)))
Out[181]: 23
维基百科将您的规范称为 "entry-wise 1,1-norm". You can compute the matrix 1-norm ("maximum absolute row sum") with numpy.linalg.norm
:
In [193]: np.linalg.norm(np.array(arr1)-np.array(arr2), 1)
Out[193]: 8.0
使用neulab计算:
首先,安装它:
pip install neulab
并使用它:
from neulab.Algorithms import ManhattanMetric
arr1 = [[29, 30, 36, 30, 18],[37, 37, 49, 54, 23]]
arr2 = [[31, 33, 37, 34, 22],[37, 38, 50, 58, 26]]
dist = ManhattanMetric(vector1=arr1, vector2=arr2)
输出:23.0
您还可以在 neulab 中使用其他指标。
阅读文档 https://pypi.org/project/neulab
对于一维 vector/array 它更容易。例如:
array1 = [1, 2, 3]
array2 = [1, 1, 1]
曼哈顿距离为:(0+1+2) 即 3
import numpy as np
def cityblock_distance(A, B):
result = np.sum([abs(a - b) for (a, b) in zip(A, B)])
return result
2 个点的输出将是:3 但是 2D array/vector 呢?例如,两个二维向量的曼哈顿(或 L1 或城市街区)将是什么(如下):
arr1 = [[29, 30, 36, 30, 18],[37, 37, 49, 54, 23]]
arr2 = [[31, 33, 37, 34, 22],[37, 38, 50, 58, 26]]
如果我使用上面提到的代码,它会给出 3 作为 1 D 向量的输出。对于 2D 向量,输出显示为 2281。在我看来,逻辑曼哈顿距离应该是这样的:
difference of the first item between two arrays: 2,3,1,4,4 which sums to 14
difference of the second item between two array:0,1,1,4,3 which is 9.
总和为 23,因此这两个二维数组之间的曼哈顿距离为 23。
是我计算有误还是我的L1距离概念有问题?
您可以修改您的代码以通过依次比较二维数组中的每个列表(使用您的一维案例代码)然后对结果求和来计算所需的结果:
def cityblock_distance(A, B):
result = np.sum([np.sum([abs(a - b) for (a, b) in zip(C, D)]) for C, D in zip(A, B)])
return result
cityblock_distance(arr1,arr2)
输出:
23
如果 arr1
和 arr2
是 numpy 数组,您可以使用:
# skip if already numpy arrays:
arr1 = np.array(arr1)
arr2 = np.array(arr2)
x = np.sum(np.abs(arr1 - arr2))
print(x)
打印:
23
您编写的代码将无法运行,即使在修复缩进后也是如此:
In [177]:
...: def cityblock_distance(A, B):
...: result = np.sum([abs(a - b) for (a, b) in zip(A, B)])
...: return result
...:
In [178]: arr1=[[29, 30, 36, 30, 18],[37, 37, 49, 54, 23]]; arr2=[[31, 3
...: 3, 37, 34, 22],[37, 38, 50, 58, 26]]
In [179]: cityblock_distance(arr1, arr2)
------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-179-d1b44e49141d> in <module>
----> 1 cityblock_distance(arr1, arr2)
<ipython-input-177-907001cbfc9b> in cityblock_distance(A, B)
1 def cityblock_distance(A, B):
----> 2 result = np.sum([abs(a - b) for (a, b) in zip(A, B)])
3 return result
<ipython-input-177-907001cbfc9b> in <listcomp>(.0)
1 def cityblock_distance(A, B):
----> 2 result = np.sum([abs(a - b) for (a, b) in zip(A, B)])
3 return result
TypeError: unsupported operand type(s) for -: 'list' and 'list'
如果转换为数组,您将获得所需的 L1 范数:
In [180]: cityblock_distance(np.array(arr1), np.array(arr2))
Out[180]: 23
但是,因为默认情况下 numpy.sum
对数组中的所有元素求和,所以您可以完全省略列表理解:
In [181]: np.sum(abs(np.array(arr1)-np.array(arr2)))
Out[181]: 23
维基百科将您的规范称为 "entry-wise 1,1-norm". You can compute the matrix 1-norm ("maximum absolute row sum") with numpy.linalg.norm
:
In [193]: np.linalg.norm(np.array(arr1)-np.array(arr2), 1)
Out[193]: 8.0
使用neulab计算:
首先,安装它:
pip install neulab
并使用它:
from neulab.Algorithms import ManhattanMetric
arr1 = [[29, 30, 36, 30, 18],[37, 37, 49, 54, 23]]
arr2 = [[31, 33, 37, 34, 22],[37, 38, 50, 58, 26]]
dist = ManhattanMetric(vector1=arr1, vector2=arr2)
输出:23.0
您还可以在 neulab 中使用其他指标。 阅读文档 https://pypi.org/project/neulab