繁体   English   中英

使用numpy数组创建最近邻居的列表

[英]Creating a list of nearest neighbors using numpy array

基于截止距离,我想创建一个点列表,这些点是给定点的邻居。 我被困在如何将点的ID添加到numpy数组中。

我在numpy数组中读取了“坐标”,如下所示:

ID x y z

1. 1 1 0.000000 3.078000 0.554000
2. 2 0.000000 3.078000 2.170000
3. 3 2.666000 1.539000 0.554000
4. 4 2.666000 1.539000 2.170000
5. 5 1.774000 0.000000 3.324000
6. 6 2.712000 0.000000 7.207000

等等...

我想要这样的输出列表

ID neighbor1 neighbor2 ....neighbor5

1. 1 4 5 6 8 
2. 2 1 4 6 n/a
3. 3 5 1 n/a 2
4. etc.

因此每个位置(1、2、3、4 ...等等)最多可以有5个邻居,如果少于5个,我想在其中放置n / a。 到目前为止,我有以下代码。

#neighborlist

flist = glob.glob(filename)

for f in flist:
    load = np.loadtxt(f, usecols=(2,3,4))
    coordinate=np.array(load)

s = (len(coordinate),6)

Nlist = np.zeros(s)

rcut = 2.5 #cutoff distance for neighbors

for f in flist:
    load = np.loadtxt(f, usecols=(2,3,4))
    coordinate=np.array(load)

for i in range(len(coordinate)):
    idx = [i,]

    for j in range(len(coordinate)):
        if np.linalg.norm(coordinate[i]-coordinate[j]) < rcut and np.linalg.norm(coordinate[i]-coordinate[j]) > 0.1:
            idx.append(j)            
        else: 
            idx = idx
    while len(idx)<6:
       idx.append('n/a')
    print idx 
    Nlist[i,:]=idx

    print Nlist

为此,我得到:

ValueError:无法将字符串转换为浮点数:n / a

因为我已经将Nlist数组的大小固定为(len(data),6)所以当邻居小于5(第一个元素是点本身)时Nlist[i,:]=idx它无法复制Nlist[i,:]=idx 在这种情况下,有没有办法动态声明Nlist或使其大小可变? 我知道这是一个棘手的问题,但必须解决这个问题。 提前致谢。

可以这样做:

import numpy as np
from collections import defaultdict

coordinate = np.array([[0.   ,  3.078,  0.554],
      [ 0.   ,  3.078,  2.17 ],
      [ 2.666,  1.539,  0.554],
      [ 2.666,  1.539,  2.17 ],
      [ 1.774,  0.   ,  3.324],
      [ 2.712,  0.   ,  7.207]])

rcut = 2.5
neighbors = defaultdict(list)

for ID1, ID2 in itertools.permutations(range(len(coordinate)), 2):
    if np.linalg.norm(coordinate[ID1]-coordinate[ID2]) < rcut:
        neighbors[ID1].append(ID2)
    else:
        neighbors[ID1].append('n/a')

for ID in neighbors:
    print ID, neighbors[ID]

输出:

0 [1, 'n/a', 'n/a', 'n/a', 'n/a']
1 [0, 'n/a', 'n/a', 'n/a', 'n/a']
2 ['n/a', 'n/a', 3, 'n/a', 'n/a']
3 ['n/a', 'n/a', 2, 4, 'n/a']
4 ['n/a', 'n/a', 'n/a', 3, 'n/a']
5 ['n/a', 'n/a', 'n/a', 'n/a', 'n/a']

请注意,我为输出使用了词典,我认为这比列表更有意义。 由于您的代码不会读取ID,而是将行号作为ID,所以我也这样做。 随着numpy从0开始编号,ID从0开始。

另请注意,您的代码只会评估文件列表中的最后一个文件,因为您会覆盖读取的每个文件的坐标数组。

为什么要在输出中存储“ n / a”,而不是简单地具有不同ID的长度可变的列表?

还要注意,我建议的代码不是很有效。 您可以使用像单元格列表这样的算法来加快处理速度。

如果您想高效地找到邻居,您可能还对scipy.spatial模块感兴趣,该模块可以做到这一点:

from scipy import spatial
kdtree = sp.spatial.KDTree(coordinate)
kdtree.query_pairs(rcut)

输出:

{(0, 1), (2, 3), (3, 4)}

这将为您提供所有距离小于rcut的点对。 这是构建所需输出列表所需的基本信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM