图论-将3D空间中的点与其他三个最近的点基于距离联系起来

问题描述

我想将节点(原子)与最近的三个节点(原子)相连。

我在做

ad1 = np.zeros((31,31))
for i in range(31):
    dist_i = dist_mat[i]
    cut_off = sorted(dist_i)[3]
    ad1[i,np.where((dist_i<=cut_off) & (dist_i!=0.0))] = 1

np.sum(ad1,axis=1) #[3,3,3........3]

np.sum(ad1,axis=0)
#array([3.,3.,2.,4.,5.,6.,3.])

我希望np.sum(ad1,axis=0)全部为3。这意味着所有节点(原子)都精确连接到3个最近的节点。如我们所见,节点/原子5连接到其他4个节点/原子,这是错误的,我希望它精确连接到3个最近的节点。我该怎么做。

下面是31个原子的距离矩阵(31 X 31)。

0.0000,6.8223,7.5588,4.8966,7.2452,2.7778,3.7082,2.7345,7.1540,6.8273,3.6995,7.4136,4.6132,5.8456,2.8037,5.4881,8.1769,2.7361,8.3034,4.9450,4.8225,4.6152,4.8243,9.4876,7.2391,2.9941,7.4180,5.8523,7.6310,5.5996,8.1761
6.8223,0.0000,3.0097,2.8567,2.6647,5.0092,5.8451,6.8037,6.7031,4.8983,7.5806,5.2873,5.5000,7.0038,4.9530,3.9763,7.0263,4.8941,4.7416,6.8450,2.8166,2.9221,5.5502,7.0328,5.5148,7.6318,2.7456,5.1150,2.9654,4.2863,5.3168
7.5588,2.8679,2.9242,5.1443,6.8372,6.5621,5.5169,3.0135,6.8412,4.6886,4.2507,5.4276,5.8673,4.8804,4.7149,6.5707,2.5568,6.3820,5.0625,4.2533,5.0600,5.2125,2.9262,7.8126,4.6864,5.4224,2.6001,3.2330,4.7116
4.8966,3.8064,3.0221,5.1335,4.1131,5.8284,2.8610,5.1354,3.8488,2.8086,4.9618,3.0028,2.7539,5.7401,4.1214,4.5830,5.4268,2.9346,2.8122,2.9319,6.8084,3.8015,5.8992,3.8516,4.9611,2.9212,3.0441,5.7392
7.2452,4.7907,5.1676,7.2899,4.5138,5.5206,7.0249,6.9978,5.3888,5.7435,6.2424,6.0645,5.2615,5.6079,2.8907,5.3589,4.7384,2.8152,6.6866,4.6140,4.7660,6.9472,5.3921,3.2734,4.7050,2.9157,2.6684
2.7778,2.8352,3.0025,4.6425,5.0210,2.8371,6.4170,2.6958,3.6516,3.1115,4.9489,5.5823,3.0042,5.5496,3.0193,4.1730,2.6916,4.1796,6.7613,4.7913,2.8772,6.4156,3.6500,5.9378,2.8228,5.5754
3.7082,5.4535,5.0179,7.5889,4.7500,8.8240,5.4549,5.4488,4.9281,6.8616,7.0789,2.8247,6.7504,3.1734,4.9441,2.9387,6.8368,7.3498,2.7571,7.6165,2.7391,7.8184,4.2915,5.4352
2.7345,6.9646,4.8923,2.8238,5.6867,2.8002,4.7436,2.7895,4.7319,7.0025,4.5800,7.4954,5.2983,5.3961,5.3071,2.7803,8.9227,5.5914,4.2758,7.1749,6.6267,6.5470,5.1104,8.2905
7.1540,6.7047,5.0056,9.1250,4.9769,2.9634,7.5819,8.5546,2.8061,6.9800,3.6751,2.5834,7.6541,4.9881,7.6494,2.7948,4.5088,5.2110,9.1264,2.9761,7.8062,2.7941,2.8038
6.8273,5.8617,2.7465,2.9301,5.1272,4.9558,3.9808,5.3162,6.8165,4.7404,6.8576,5.5561,5.5098,7.0330,2.6644,7.6461,5.2912,7.0096,2.9674,4.2945,7.0258
3.6995,7.6266,2.9474,2.7359,4.9270,6.8677,5.4363,5.4517,6.7478,3.1721,6.8329,5.4529,4.9555,7.3438,5.1708,2.7597,8.8287,5.4452,7.8249,4.2909,7.0646
7.4136,4.9529,7.5866,4.8602,2.7541,8.0299,7.1729,7.0207,8.9107,5.2910,6.5588,2.9146,9.5249,5.3922,9.1160,4.1719,8.7725,2.7497,6.4529,9.0793
4.6132,2.8097,3.9433,4.7505,4.4056,5.3122,4.8719,4.3293,5.3691,4.4387,2.8442,6.4077,2.8070,4.8696,6.5606,5.3482,5.0545,2.9281,6.2031
5.8456,6.2398,7.3805,2.7234,6.6316,4.5653,2.8038,7.3250,5.3513,5.6427,4.8167,3.2793,4.4545,8.7753,4.6687,2.8747,5.2395
2.8037,2.6964,7.9654,2.7924,7.3935,6.1211,2.8429,3.9452,2.8424,9.2720,6.2355,5.1988,4.8668,6.2430,5.2004,5.1737,7.9659
5.4881,8.3401,4.7306,7.1148,7.8221,2.7718,4.7476,2.7753,9.5030,6.0617,7.5711,2.7577,7.3777,3.1397,5.7882,8.3392
8.1769,8.3066,2.9172,4.5762,8.3187,6.2166,6.9974,2.6988,2.6667,6.8504,9.0816,5.2518,7.0366,3.3010,4.3079
2.7361,7.5094,5.3015,2.7788,2.8080,5.4012,8.9373,7.2956,4.2691,5.6901,4.7565,6.5515,5.1204,7.0169
8.3034,5.4477,6.7736,4.8812,6.7675,2.6661,2.8871,7.5857,7.0211,4.5660,5.1569,2.7695,2.9165
4.9450,6.7806,4.3263,6.7865,5.3395,5.3642,2.6393,8.9072,2.7997,8.0722,3.1518,4.5623
4.8225,2.8411,4.6768,8.8466,6.6849,6.5259,2.9190,5.6409,4.2802,5.1556,7.0036
4.6152,5.3713,4.8619,4.9490,2.8105,5.0539,2.9321,4.4129
4.8243,8.8413,4.7294,6.5361,5.2956,7.3262,4.2788,8.3129
9.4876,4.6127,7.9200,9.5247,4.8201,7.8081,4.1075,2.6956
7.2391,6.9513,6.9963,5.7431,4.7049,2.9171,5.2546
2.9941,9.1125,4.4513,8.8145,4.8939,6.8395
7.4180,7.5797,2.7482,6.4514,8.0302
5.8523,7.1676,2.8724,2.7190
7.6310,5.1559,7.0354
5.5996,3.2927
8.1761,5.3168,4.7116,5.7392,2.6684,5.5754,5.4352,8.2905,7.0258,7.0646,9.0793,6.2031,5.2395,7.9659,8.3392,4.3079,7.0169,2.9165,4.5623,7.0036,4.4129,8.3129,2.6956,5.2546,6.8395,8.0302,2.7190,7.0354,3.2927,0.0000

编辑1

谢谢你,@ yatu和@mathfux,但Kdtree不能满足我的需求。

因此从@mathfux答案如果3的最接近列表是0,1,2,而0的最接近列表是1,4,2,则该算法应更加重视距离并断开3和0的连接。 3应该找到距离它最近的其他点,而不是与0连接。如果3无法找到距离它最近的其他点,则0必须基于距离排除1或2并包括3,因为3不能找到3个除了它之外的最近点0,2。

还可以看到0连接到25,但是25没有连接到0,这是错误的。如果0连接到25,则25也应该连接到0。

[ 0,17,7,25]
[ 5,21,12,6]
[ 6,25,27,17]
[10,13,7]
[12,5,24]
[21,4]
[25,6,10,19]
[29,24]

解决方法

KDTree更适合您要执行的操作。构建完树后,您可以搜索与树中所有点最接近的d = dict.fromkeys(df.columns.difference(['a','b']),'first') d['c'] = 'mean' print (d) {'c': 'mean','d': 'first'} df = df.groupby(["a","b"],as_index=False).agg(d) print (df) a b c d 0 c a 1.0 True 1 f e 2.5 True 点:

3

要检查结果,我们可以验证第一行中的三个最小值与第一行from sklearn.neighbors import KDTree tree = KDTree(X,leaf_size=2) dist,ind = tree.query(X,k=3) 上的query索引返回的三个最小距离相匹配:

ind[0]
,

由于您无法保持矩阵对称,因此这种连接似乎并不总是可能的。实际上,不需要距离矩阵进行解释。

import matplotlib.pyplot as plt
points = np.array([[0,0],[0,1],-1],[1,[-0.5,0]])
plt.scatter(*np.transpose(points))
for i in range(len(points)):
    plt.text(points[i][0],points[i][1],1,2,3,4][i],fontsize=24)

enter image description here

假设您为点0找到3个最接近的点123,这并不意味着3个在最近的列表中点为0。

如果您仍然想找到3个最接近的点,则根本不需要该循环,只需使用np.argsort(dist_mat,axis=1)[:,1:4]来查找最近点的索引或使用np.sort(dist_mat,1:4]来查找距离。如果您需要使用点而不是dist_max(这是开销),则KDTree是更好的选择。