0

我有一个 nd 数组,如下所示:

[[ 0.          1.73205081  6.40312424  7.21110255  2.44948974]
 [ 1.73205081  0.          5.09901951  5.91607978  1.        ]
 [ 6.40312424  5.09901951  0.          1.          4.35889894]
 [ 7.21110255  5.91607978  1.          0.          5.09901951]
 [ 2.44948974  1.          4.35889894  5.09901951  0.        ]]

这个数组中的每个元素都是一个距离,我需要把它变成一个带有行、列、距离的列表,如下所示:

l = [(0,0,0),(0,1, 1.73205081),(0,2, 6.40312424),...,(1,0, 1.73205081),(1,1,0),...,(4,4,0)] 

此外,删除对角元素以及元素 (j,i) 作为 (i,j) 已经存在会很酷。本质上,是否可以只取其顶部的三角矩阵?

这是否可以有效地完成(没有很多循环)?我用方形创建了这个数组,但找不到任何文档来做这个。

4

4 回答 4

4

squareform做这一切。阅读文档并进行实验。它在两个方向都有效。如果你给它一个矩阵,它会返回上三角值(压缩形式)。如果你给它这些值,它会返回矩阵。

In [668]: M
Out[668]: 
array([[ 0. ,  0.1,  0.5,  0.2],
       [ 0.1,  0. ,  2. ,  0.3],
       [ 0.5,  2. ,  0. ,  0.2],
       [ 0.2,  0.3,  0.2,  0. ]])
In [669]: spatial.distance.squareform(M)
Out[669]: array([ 0.1,  0.5,  0.2,  2. ,  0.3,  0.2])
In [670]: v=spatial.distance.squareform(M)
In [671]: v
Out[671]: array([ 0.1,  0.5,  0.2,  2. ,  0.3,  0.2])
In [672]: spatial.distance.squareform(v)
Out[672]: 
array([[ 0. ,  0.1,  0.5,  0.2],
       [ 0.1,  0. ,  2. ,  0.3],
       [ 0.5,  2. ,  0. ,  0.2],
       [ 0.2,  0.3,  0.2,  0. ]])

您还可以指定一个forcechecks参数,但没有这些参数,它只是按形状。

指标可以来自triu

In [677]: np.triu_indices(4,1)
Out[677]: 
(array([0, 0, 0, 1, 1, 2], dtype=int32),
 array([1, 2, 3, 2, 3, 3], dtype=int32))

In [680]: np.vstack((np.triu_indices(4,1),v)).T
Out[680]: 
array([[ 0. ,  1. ,  0.1],
       [ 0. ,  2. ,  0.5],
       [ 0. ,  3. ,  0.2],
       [ 1. ,  2. ,  2. ],
       [ 1. ,  3. ,  0.3],
       [ 2. ,  3. ,  0.2]])

只是为了检查,我们可以用这些值填充一个 4x4 矩阵

In [686]: A=np.vstack((np.triu_indices(4,1),v)).T
In [687]: MM = np.zeros((4,4))
In [688]: MM[A[:,0].astype(int),A[:,1].astype(int)]=A[:,2]
In [689]: MM
Out[689]: 
array([[ 0. ,  0.1,  0.5,  0.2],
       [ 0. ,  0. ,  2. ,  0.3],
       [ 0. ,  0. ,  0. ,  0.2],
       [ 0. ,  0. ,  0. ,  0. ]])

这些triu索引还可以从以下位置获取值M

In [693]: I,J = np.triu_indices(4,1)
In [694]: M[I,J]
Out[694]: array([ 0.1,  0.5,  0.2,  2. ,  0.3,  0.2])

squareform使用编译后的代码,spatial.distance._distance_wrap所以我希望它对于大型数组来说会非常快。唯一的问题是它只返回压缩形式的值,而不是索引。但是给定形状,指数总是可以计算出来的。它们不需要与值一起存储。

于 2017-01-30T06:04:59.917 回答
2

如果您的输入是x,首先生成索引:

i0,i1 = np.indices(x.shape)

然后:

np.concatenate((i1,i0,x)).reshape(3,5,5).T

这给了你第一个结果——对于整个矩阵。

至于只取上三角形,您可能会考虑尝试np.triu(),但我不确定您正在寻找什么结果。不过,您可能现在可以弄清楚如何掩盖您不想要的部分。

于 2017-01-30T05:50:41.890 回答
0

你可以试试这个

print([(x,y, value) for (x,y), value in np.ndenumerate(numpymatrixarray)])

output [(0, 0, 0.0), (0, 1, 1.7320508100000001), (0, 2, 6.4031242400000004), (0, 3, 7.2111025499999997), (0, 4, 2.4494897400000002), (1, 0, 1.7320508100000001), (1, 1, 0.0), (1, 2, 5.0990195099999998), (1, 3, 5.9160797799999996), (1, 4, 1.0), (2, 0, 6.4031242400000004), (2, 1, 5.0990195099999998), (2, 2, 0.0), (2, 3, 1.0), (2, 4, 4.3588989400000004), (3, 0, 7.2111025499999997), (3, 1, 5.9160797799999996), (3, 2, 1.0), (3, 3, 0.0), (3, 4, 5.0990195099999998), (4, 0, 2.4494897400000002), (4, 1, 1.0), (4, 2, 4.3588989400000004), (4, 3, 5.0990195099999998), (4, 4, 0.0)]
于 2017-01-30T05:57:28.290 回答
0

你真的想要一个[nxm]矩阵的顶部三角矩阵n>m吗?这将为您提供(nxn-n)/2元素并丢失m⊖n.

您可能想要的是下三角矩阵:

def tri_reduce(m):
    n=m.shape
    if n[0]>n[1]:
        i=np.tril_indices(n[0],1,n[1])
    else:
        i=np.triu_indices(n[0],1,n[1])
    return np.vstack((i,m[i])).T

尽管我相信,将它重建成一个元组列表需要一个循环。 list(tri_reduce(m))将给出 nd 数组的列表。

于 2017-01-30T07:33:58.777 回答