首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >大型矩阵排序,然后找出最小的元素及其索引成一个列表。

大型矩阵排序,然后找出最小的元素及其索引成一个列表。
EN

Stack Overflow用户
提问于 2017-01-31 16:05:10
回答 1查看 199关注 0票数 3

我有一个比较大的矩阵M。我试图找到前5位最近的距离,以及他们的指数。

代码语言:javascript
复制
M = csr_matrix(M)
dst = pairwise_distances(M,Y=None,metric='euclidean')

dst成为一个巨大的矩阵,我正试图有效地对它进行排序,或者使用枕木或滑雪板来找到最近的5段距离。

下面是我想要做的事情的一个例子:

代码语言:javascript
复制
X = np.array([[2, 3, 5], [2, 3, 6], [2, 3, 8], [2, 3, 3], [2, 3, 4]]) 

然后,我将dst计算为:

代码语言:javascript
复制
[[ 0.  1.  3.  2.  1.]
 [ 1.  0.  2.  3.  2.]
 [ 3.  2.  0.  5.  4.]
 [ 2.  3.  5.  0.  1.]
 [ 1.  2.  4.  1.  0.]]

所以,第0行本身有一个0.的距离,第0行到第1行的距离是1.,.第2行到第3行的距离为5.,依此类推。我想找到这些最近的5个距离,并将它们放在一个列表中,其中包含相应的行,比如距离、行、行。我不想要任何对角线元素或重复元素,所以我采用下面的上三角矩阵:

代码语言:javascript
复制
[[ inf   1.   3.   2.   1.]
 [ nan  inf   2.   3.   2.]
 [ nan  nan  inf   5.   4.]
 [ nan  nan  nan  inf   1.]
 [ nan  nan  nan  nan  inf]]

现在,前5位距离最小到最大的是:

代码语言:javascript
复制
[1, 0, 1], [1, 0, 4], [1, 3, 4], [2, 1, 2], [2, 0, 3], [2, 1, 4] 

如您所见,有三个元素具有距离2,三个元素具有距离1。从这些元素中,我想随机选择一个具有距离2的元素,因为我只想要顶部的f元素,在本例中是f=5。

这只是一个样本,因为这个矩阵可能很大。除了使用基本的排序函数之外,是否有一种有效的方法来完成上述工作?我找不到任何滑雪板或乐土来帮助我。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-02-01 01:26:15

下面是一个完全矢量化的解决方案:

代码语言:javascript
复制
import numpy as np
from scipy.spatial.distance import pdist

def smallest(M, f):
    # compute the condensed distance matrix
    dst = pdist(M, 'euclidean')
    # indices of the upper triangular matrix
    rows, cols = np.triu_indices(M.shape[0], k=1)
    # indices of the f smallest distances
    idx = np.argsort(dst)[:f]
    # gather results in the specified format: distance, row, column
    return np.vstack((dst[idx], rows[idx], cols[idx])).T

注意,np.argsort(dst)[:f]生成按升序排序的凝聚距离矩阵dst中最小f元素的索引。

下面的演示再现了玩具示例的结果,并展示了函数smallest如何处理相当大的

整数:

代码语言:javascript
复制
In [59]: X = np.array([[2, 3, 5], [2, 3, 6], [2, 3, 8], [2, 3, 3], [2, 3, 4]])

In [60]: smallest(X, 5)
Out[60]: 
array([[ 1.,  0.,  1.],
       [ 1.,  0.,  4.],
       [ 1.,  3.,  4.],
       [ 2.,  0.,  3.],
       [ 2.,  1.,  2.]])

In [61]: large_X = np.random.randint(100, size=(10000, 2000))

In [62]: large_X
Out[62]: 
array([[ 8, 78, 97, ..., 23, 93, 90],
       [42,  2, 21, ..., 68, 45, 62],
       [28, 45, 30, ...,  0, 75, 48],
       ..., 
       [26, 88, 78, ...,  0, 88, 43],
       [91, 53, 94, ..., 85, 44, 37],
       [39,  8, 10, ..., 46, 15, 67]])

In [63]: %time smallest(large_X, 5)
Wall time: 1min 32s
Out[63]: 
array([[ 1676.12529365,  4815.        ,  5863.        ],
       [ 1692.97253374,  1628.        ,  2950.        ],
       [ 1693.558384  ,  5742.        ,  8240.        ],
       [ 1695.86408654,  2140.        ,  6969.        ],
       [ 1696.68853948,  5477.        ,  6641.        ]])
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41962084

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档