使用numpy数组

时间:2015-08-14 08:54:43

标签: python arrays numpy

基于截止距离,我想创建一个点列表,这些点是给定点的邻居。我遇到了如何将点的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:无法将字符串转换为float:n / a

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

1 个答案:

答案 0 :(得分:1)

可以这样做:

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设置不同长度的列表?

另请注意,我建议的代码效率不高。您可以使用cell lists等算法来加快速度。

如果你想有效地找到邻居,你可能也会对scipy.spatial模块感兴趣:

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

输出:

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

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