欧几里德距离的 Delaney 三角剖分 - Scipy

5
从Scipy导入的空间包(spatial)可以测量指定点之间的欧几里得距离。是否可能使用Delaunay包返回相同的测量结果?使用下面的df,按Time分组测量所有点之间的平均距离。然而,我希望使用Delaunay三角剖分来测量平均距离。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Delaunay

df = pd.DataFrame({
    'Time' : [1,1,1,1,2,2,2,2],                  
    'A_X' : [5, 5, 6, 6, 4, 3, 3, 4], 
    'A_Y' : [5, 6, 6, 5, 5, 6, 5, 6],                         
        })

def make_points(x):
    return np.array(list(zip(x['A_X'], x['A_Y'])))

points = df.groupby("Time").apply(make_points)

for p in points:
    tri = Delaunay(p)
    ax.triplot(*p.T, tri.simplices)

可以使用以下方法来测量所有点之间的平均距离,但我希望加入Delaunay。

 avg_dist = (df.groupby(['Time'])
             .apply(lambda x: spatial.distance.pdist
             (np.array(list(zip(x['A_X'], x['A_Y']))))
             .mean() if len(x) > 1 else 0)
             .reset_index()
             )

预期输出:

   Time         0
0     1  1.082842
1     2  1.082842
1个回答

5
你可以尝试这个函数。
from itertools import combinations
import numpy as np
    
def edges_with_no_replacement(points):
    
    # get the unique coordinates
    points = np.unique(points.loc[:,['A_X','A_Y']].values,return_index=False,axis=0)
    if len(points) <= 1: return 0
    # for two points, no triangle
    # I think return the distance between the two points make more sense? You can change the return value to zero.
    if len(points) == 2: return np.linalg.norm(points[0]-points[1])
    
    tri = Delaunay(points)
    triangles = tri.simplices
    # get all the unique edges 
    all_edges = set([tuple(sorted(edge)) for item in triangles for edge in combinations(item,2)])
    # compute the average dist 
    return np.mean([np.linalg.norm(points[edge[0]]-points[edge[1]]) for edge in all_edges])

此函数首先找出给定三角形的所有唯一边,然后返回三角形边缘的平均长度。应用此函数。

avg_dist = (df.groupby(['Time']).apply(edges_with_no_replacement).reset_index())

输出结果为

    Time    0
0   1   1.082843
1   2   1.082843

需要注意的是,edges_with_no_replacement函数仍会在点共线时抛出QhullError异常,例如:

Delaunay(np.array([[1,2],[1,3],[1,4]]))

因此,您必须确保这些点不在同一条线上。


抱歉,这是一个快速的问题。我会修改问题,但如果我没有足够的点来计算,我希望返回0。但是我收到了一个错误信息:`QhullError: QH6214 qhull输入错误:没有足够的点(2)构造初始单纯形(需要4)执行时:| qhull d Qc Q12 Qz Qbb Qt 选择的选项为Qhull 2019.1.r 2019/06/21: run-id 974469614 delaunay Qcoplanar-keep Q12-allow-wide Qz-infinity-point Qbbound-last Qtriangulate _pre-merge _zero-centrum Qinterior-keep _maxoutside 0` - jonboy
1
@jonboy 我更新了文章,edges_with_no_replacement 函数现在可以处理仅有两个唯一点的情况。但请注意,如果这些点在同一直线上,该函数仍会引发错误。 - meTchaikovsky
谢谢。所以如果是0-1点,返回0。如果是2个点,则返回它们之间的距离。如果点在同一条线上,你是什么意思? - jonboy
1
@jonboy 不客气,在我的更新帖子中,我提供了一个例子,如果点在同一条线上,Delaunay 就无法找到三角形(毕竟没有三角形)。如果您的数据集中有这样的点,您也会收到 QhullError - meTchaikovsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接