我有一個這樣的陣列,我必須找到每個點之間的距離。如何在 python 中使用 numpy 執行此操作?
[ 8139, 115665],
[ 8132, 126563],
[ 8193, 113938],
[ 8193, 123714],
[ 8156, 120291],
[ 8373, 125253],
[ 8400, 131442],
[ 8400, 136354],
[ 8401, 129352],
[ 8439, 129909],
[ 8430, 135706],
[ 8430, 146359],
[ 8429, 139089],
[ 8429, 133243]```
uj5u.com熱心網友回復:
您可以使用np.repeatandnp.tile創建所有組合,然后計算歐幾里得距離:
xy = np.array([[8139, 115665], [8132, 126563], [8193, 113938], [8193, 123714],
[8156, 120291], [8373, 125253], [8400, 131442], [8400, 136354],
[8401, 129352], [8439, 129909], [8430, 135706], [8430, 146359],
[8429, 139089], [8429, 133243]])
a = np.repeat(xy, len(xy), axis=0)
b = np.tile(xy, [len(xy), 1])
d = np.sqrt(np.sum((a - b) ** 2, axis=1))
的輸出d是 (196,),即 14 x 14。
更新
但我必須在一個函式中做到這一點。
def distance(xy):
a = np.repeat(xy, len(xy), axis=0)
b = np.tile(xy, [len(xy), 1])
return np.sqrt(np.sum((a - b) ** 2, axis=1))
d = distance(xy)
uj5u.com熱心網友回復:
讓我們將此問題最小化為 4 點:
points = np.array([[8139, 115665], [8132, 126563], [8193, 113938], [8193, 123714]])
一般來說,你需要做2個步驟:
- 為您想要獲取的點對創建索引
- 申請
np.hypot這些對。
TL;博士
制作點的索引
有很多方法可以為您想要獲取的每對點創建索引對。但它們來自哪里?在每種情況下,從鄰接矩陣開始構建它們都是一個好主意。
情況1
以最常見的方式,您可以像這樣開始構建它:
adjacency = np.ones(shape=(len(points), len(points)), dtype=bool)
>>> adjacency
[[ True True True True]
[ True True True True]
[ True True True True]
[ True True True True]]
它對應于您需要采取的索引,如下所示:
adjacency_idx_view = np.transpose(np.nonzero(adjacency))
for n in adjacency_idx_view.reshape(len(points), len(points), 2):
>>> print(n.tolist())
[[0, 0], [1, 0], [2, 0], [3, 0]]
[[0, 1], [1, 1], [2, 1], [3, 1]]
[[0, 2], [1, 2], [2, 2], [3, 2]]
[[0, 3], [1, 3], [2, 3], [3, 3]]
這就是你收集它們的方式:
x, y = np.nonzero(adjacency)
>>> np.transpose([x, y])
array([[0, 0],
[0, 1],
[0, 2],
[0, 3],
[1, 0],
[1, 1],
[1, 2],
[1, 3],
[2, 0],
[2, 1],
[2, 2],
[2, 3],
[3, 0],
[3, 1],
[3, 2],
[3, 3]], dtype=int64)
也可以像@Corralien 的回答那樣手動完成:
x = np.repeat(np.arange(len(points)), len(points))
y = np.tile(np.arange(len(points)), len(points))
案例2
在以前的情況下,每對點都是重復的。還有點重復的對。一個更好的選擇是忽略這些過多的資料,只取第一個點的索引小于第二個點的索引的對:
adjacency = np.less.outer(np.arange(len(points)), np.arange(len(points)))
>>> print(adjacency)
[[False True True True]
[False False True True]
[False False False True]
[False False False False]]
x, y = np.nonzero(adjacency)
這沒有被廣泛使用。盡管這超出了np.triu_indices. 因此,作為替代方案,我們可以使用:
x, y = np.triu_indices(len(points), 1)
這導致:
>>> np.transpose([x, y])
array([[0, 1],
[0, 2],
[0, 3],
[0, 4],
[1, 2],
[1, 3],
[1, 4],
[2, 3],
[2, 4],
[3, 4]])
案例 3 您也可以嘗試僅省略成對的重復點,并留下點對被交換。與案例 1一樣,它需要 2 倍的記憶體和消耗時間,所以我將其僅用于演示目的:
adjacency = ~np.identity(len(points), dtype=bool)
>>> adjacency
array([[False, True, True, True],
[ True, False, True, True],
[ True, True, False, True],
[ True, True, True, False]])
x, y = np.nonzero(adjacency)
>>> np.transpose([x, y])
array([[0, 1],
[0, 2],
[0, 3],
[1, 0],
[1, 2],
[1, 3],
[2, 0],
[2, 1],
[2, 3],
[3, 0],
[3, 1],
[3, 2]], dtype=int64)
我將把制作x和y手動(不遮罩)作為其他人的練習。
申請 np.hypot
而不是np.sqrt(np.sum((a - b) ** 2, axis=1))你可以做的np.hypot(np.transpose(a - b))。我將案例 2作為我的索引生成器:
def distance(points):
x, y = np.triu_indices(len(points), 1)
x_coord, y_coord = np.transpose(points[x] - points[y])
return np.hypot(x_coord, y_coord)
>>> distance(points)
array([10898.00224812, 1727.84403231, 8049.18113848, 12625.14736548,
2849.65296133, 9776. ])
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/414373.html
標籤:
