【问题标题】:Numpy - Extracting Unique Values from a Distance MatrixNumpy - 从距离矩阵中提取唯一值
【发布时间】:2018-06-12 20:38:50
【问题描述】:

输入数据:

我有以下distance_matrix

  [[1.        , 0.14285714, 0.25      , 0.83333333, 0.63636364],
   [0.14285714, 1.        , 0.33333333, 0.84615385, 0.66666667],
   [0.25      , 0.33333333, 1.        , 0.76923077, 0.58333333],
   [0.83333333, 0.84615385, 0.76923077, 1.        , 0.69230769],
   [0.63636364, 0.66666667, 0.58333333, 0.69230769, 1.        ]]

当前结果:

np.where(distane_matrix <= 0.25) 返回以下输出:

(array([0, 0, 1, 2]), array([1, 2, 0, 0]))

期望的结果:

(array([0, 0]), array([1, 2]))

说明:

用文字来表达,因为我知道:

  1. [0,1][1,0] 具有相同的值
  2. [0,2][2,0] 具有相同的值
  3. [0,1][0,2]满足np.where()的要求

我确实希望在输出中返回[1,0][2,0],因为它是冗余信息。最好的方法是什么?

【问题讨论】:

  • 这看起来不太像距离矩阵,对角线上的 1 是什么。
  • 感谢您指出这一点。对角线上应该是 0。尽管如此,我会保持原来的帖子不变,以便将来的用户更容易阅读答案。

标签: python arrays numpy scipy


【解决方案1】:

假设d是一个指定的距离矩阵。

演示:

In [28]: r = np.triu(d, 1)

In [29]: r
Out[29]:
array([[0.        , 0.14285714, 0.25      , 0.83333333, 0.63636364],
       [0.        , 0.        , 0.33333333, 0.84615385, 0.66666667],
       [0.        , 0.        , 0.        , 0.76923077, 0.58333333],
       [0.        , 0.        , 0.        , 0.        , 0.69230769],
       [0.        , 0.        , 0.        , 0.        , 0.        ]])

In [30]: np.where((r>0) & (r<=0.25))
Out[30]: (array([0, 0], dtype=int64), array([1, 2], dtype=int64))

【讨论】:

  • 认为 OP 想要 tril 索引?
  • @Divakar,距离矩阵通常是对称的,所以结果应该不会不同......
  • 啊,没错。如果里面有 0 怎么办?
  • @Divakar,这意味着这是同一点的距离,通常被忽略...
  • @Divakar,我假设这些点的距离并不有趣
【解决方案2】:

如果您想要一个独立于选择标准的解决方案,您可以考虑使用掩码数组:

import numpy.ma as ma

mat_masked = ma.array(your_mat, mask = np.triu(np.ones(np.shape(your_mat))))

从这里你会像以前一样继续前进

np.where(mat_masked <= 0.25) 

这还有一个好处是您的数据不会受到影响。

【讨论】:

    【解决方案3】:

    这是masking 的一种方法-

    def get_lower_indices(a, thresh=0.25):
        n = a.shape[0]    
        ra = np.arange(n)
        mask = ra[:,None] < ra
        v = np.flatnonzero(a[mask] <= thresh)
        idx = np.concatenate(( [0], np.arange(n-1,0,-1).cumsum() ))
        c = np.searchsorted(idx, v,'right')-1
        r = v-idx[c]+c+1    
        return c,r
    

    示例运行 -

    In [116]: a
    Out[116]: 
    array([[1.        , 0.14285714, 0.25      , 0.83333333, 0.63636364],
           [0.14285714, 1.        , 0.33333333, 0.84615385, 0.66666667],
           [0.25      , 0.33333333, 1.        , 0.76923077, 0.58333333],
           [0.83333333, 0.84615385, 0.76923077, 1.        , 0.69230769],
           [0.63636364, 0.66666667, 0.58333333, 0.69230769, 1.        ]])
    
    In [117]: get_lower_indices(a, thresh=0.25)
    Out[117]: (array([0, 0]), array([1, 2]))
    

    如果您可以将上三角元素编辑为更高的值,这不会在阈值操作中被捕获,我们可以按照这些思路做一些事情 -

    def get_lower_indices_mask_editing(a, thresh=0.25):
        n = a.shape[0]
        r = np.arange(n)
        a[r[:,None] >= r] = 1
        return np.where(a<=thresh)
    

    其他方法:

    # @MaxU's soln
    def triu_where(d):
        r = np.triu(d, 1)
        return np.where((r>0) & (r<=0.25))
    

    时间安排 -

    In [231]: # Setup random array with larger size and no zeros
         ...: np.random.seed(0)
         ...: N = 5000
         ...: data = np.random.rand(N,N)
         ...: data = data.dot(data.T)
         ...: data = (data - data.min())/(data.max() -data.min())
         ...: data[data==0] = 0.1
         ...: np.fill_diagonal(data,1)
    
    # @MaxU's soln
    In [232]: %timeit triu_where(data)
    10 loops, best of 3: 174 ms per loop
    
    In [233]: %timeit get_lower_indices(data, thresh=0.25)
    1 loop, best of 3: 318 ms per loop
    
    In [234]: %timeit get_lower_indices_mask_editing(data, thresh=0.25)
    10 loops, best of 3: 150 ms per loop
    

    【讨论】:

    • 在问题中,所需的结果是上三角形中的索引。这是一个微不足道的变化,但为什么不符合预期的结果?
    • @WarrenWeckesser 所需的结果也可以被认为是下三角形,最终输出将采用 col、row 格式。如果我使用较低的三角形元素,我使用np.concatenate(( [0], np.arange(1,n).cumsum() )) 设置增量“三角形”步进数组的方式会更容易。
    • @WarrenWeckesser 经过仔细检查,似乎顺序会有所不同。以上三角区域为焦点进行编辑。
    【解决方案4】:

    不要使用np.triu,而是使用np.triu_indices。以d为距离矩阵:

    def dist_thr(d, thr = .25):
        i, j = triu_indices(d.shape[0], 1)
        mask = d[i, j] < thr
        return i[mask], j[mask]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      • 2017-01-07
      • 2014-08-07
      • 1970-01-01
      相关资源
      最近更新 更多