我有一个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)已经存在,这将是很酷的。基本上,是否可以只采用这个顶部三角矩阵?
这是否可以有效地完成(没有很多循环)?我用方形创建了这个数组,但是找不到任何文档可以做到这一点。
答案 0 :(得分: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. ]])
您还可以指定force
和checks
参数,但如果没有这些参数,则只能按形状进行。
指标可以来自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
中的编译代码,所以我希望它对于大型数组来说会非常快。唯一的问题是它只返回压缩的表单值,而不是索引。但考虑到形状,可以始终计算指数。他们不需要与值一起存储。
答案 1 :(得分:2)
如果您的输入为x
,请先生成索引:
i0,i1 = np.indices(x.shape)
然后:
np.concatenate((i1,i0,x)).reshape(3,5,5).T
这为您提供了整个矩阵的第一个结果。
至于只拍摄上三角形,您可能会考虑尝试np.triu()
,但我不确定您正在寻找的确切结果。你可以弄清楚如何掩盖你现在不想要的部分。
答案 2 :(得分: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)]
答案 3 :(得分: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数组列表。