在大型numpy三维数组上计算二维成对距离 [英] Calculate two dimensional pairwise distance on a large numpy three dimensional array

查看:212
本文介绍了在大型numpy三维数组上计算二维成对距离的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个以[pt_id, x, y, z]形式的300万个点的numpy数组.目标是返回所有具有欧氏距离的两个数字min_dmax_d的所有点对.

I have a numpy array of 3 million points in the form of [pt_id, x, y, z]. The goal is to return all pairs of points that have an Euclidean distance two numbers min_d and max_d.

欧几里德距离在xy之间,而不在z上.但是,我想保留具有pt_id_frompt_id_todistance属性的数组.

The Euclidean distance is between x and y and not on the z. However, I'd like to preserve the array with pt_id_from, pt_id_to, distance attributes.

我正在使用scipy的dist计算距离:

I'm using scipy's dist to calculate the distances:

import scipy.spatial.distance
coords_arr = np.array([['pt1', 2452130.000, 7278106.000, 25.000],
                       ['pt2', 2479539.000, 7287455.000, 4.900],
                       ['pt3', 2479626.000, 7287458.000, 10.000],
                       ['pt4', 2484097.000, 7292784.000, 8.800],
                       ['pt5', 2484106.000, 7293079.000, 7.300],
                       ['pt6', 2484095.000, 7292891.000, 11.100]])

dists = scipy.spatial.distance.pdist(coords_arr[:,1:3], 'euclidean')
np.savetxt('test.out', scipy.spatial.distance.squareform(dists), delimiter=',')

我该怎么做才能返回以下形式的数组:[pt_id_from, pt_id_to, distance]?

What should I do to return an array of form: [pt_id_from, pt_id_to, distance]?

推荐答案

好吧,['pt1', 'pt2', distance_as_number]并非完全可能.您可以使用混合数据类型获得的最接近的是结构化数组,但是您不能执行result[:2,0]之类的操作.您必须分别索引字段名称和数组索引,例如:result[['a','b']][0].

Well, ['pt1', 'pt2', distance_as_number] is not exactly possible. The closest you can get with mixed datatypes is a structured array but then you can't do things like result[:2,0]. You'll have to index field names and array indices separately like: result[['a','b']][0].

这是我的解决方案:

import numpy as np
import scipy.spatial.distance

coords_arr = np.array([['pt1', 2452130.000, 7278106.000, 25.000],
                       ['pt2', 2479539.000, 7287455.000, 4.900],
                       ['pt3', 2479626.000, 7287458.000, 10.000],
                       ['pt4', 2484097.000, 7292784.000, 8.800],
                       ['pt5', 2484106.000, 7293079.000, 7.300],
                       ['pt6', 2484095.000, 7292891.000, 11.100]])

dists = scipy.spatial.distance.pdist(coords_arr[:,1:3], 'euclidean')

# Create a shortcut for `coords_arr.shape[0]` which is basically
# the total amount of points, hence `n`
n = coords_arr.shape[0]

# `a` and `b` contain the indices of the points which were used to compute the
# distances in dists. In this example:
# a = [0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4]
# b = [1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5]
a = np.arange(n).repeat(np.arange(n-1, -1, -1))
b = np.hstack([range(x, n) for x in xrange(1, n)])

min_d = 1000
max_d = 10000

# Find out which distances are in range.
in_range = np.less_equal(min_d, dists) & np.less_equal(dists, max_d)

# Define the datatype of the structured array which will be the result.
dtype = [('a', '<f8', (3,)), ('b', '<f8', (3,)), ('dist', '<f8')]

# Create an empty array. We fill it later because it makes the code cleaner.
# Its size is given by the sum over `in_range` which is possible
# since True and False are equivalent to 1 and 0.
result = np.empty(np.sum(in_range), dtype=dtype)

# Fill the resulting array.
result['a'] = coords_arr[a[in_range], 1:4]
result['b'] = coords_arr[b[in_range], 1:4]
result['dist'] = dists[in_range]

print(result)

# In caste you don't want a structured array at all, this is what you can do:
result = np.hstack([coords_arr[a[in_range],1:],
                    coords_arr[b[in_range],1:],
                    dists[in_range, None]]).astype('<f8')
print(result)

结构化数组:

[([2479539.0, 7287455.0, 4.9], [2484097.0, 7292784.0, 8.8], 7012.389393067102)
 ([2479539.0, 7287455.0, 4.9], [2484106.0, 7293079.0, 7.3], 7244.7819152821985)
 ([2479539.0, 7287455.0, 4.9], [2484095.0, 7292891.0, 11.1], 7092.75912462844)
 ([2479626.0, 7287458.0, 10.0], [2484097.0, 7292784.0, 8.8], 6953.856268287403)
 ([2479626.0, 7287458.0, 10.0], [2484106.0, 7293079.0, 7.3], 7187.909362255481)
 ([2479626.0, 7287458.0, 10.0], [2484095.0, 7292891.0, 11.1], 7034.873843929257)]

ndarray:

[[2479539.0, 7287455.0, 4.9, 2484097.0, 7292784.0, 8.8, 7012.3893],
 [2479539.0, 7287455.0, 4.9, 2484106.0, 7293079.0, 7.3, 7244.7819],
 [2479539.0, 7287455.0, 4.9, 2484095.0, 7292891.0, 11.1, 7092.7591],
 [2479626.0, 7287458.0, 10.0, 2484097.0, 7292784.0, 8.8, 6953.8562],
 [2479626.0, 7287458.0, 10.0, 2484106.0, 7293079.0, 7.3, 7187.9093],
 [2479626.0, 7287458.0, 10.0, 2484095.0, 7292891.0, 11.1, 7034.8738]]

这篇关于在大型numpy三维数组上计算二维成对距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆