Numpy - 从距离矩阵中提取唯一值

时间:2018-06-12 20:38:50

标签: python arrays numpy scipy

输入数据:

我有以下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. 的值相同
  3. [0,2][2,0]
  4. 的值相同
  5. [0,1][0,2]符合np.where()
  6. 的要求

    希望在输出中返回[1,0][2,0],因为它是冗余信息。这样做的最佳方式是什么?

4 个答案:

答案 0 :(得分:3)

假设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))

答案 1 :(得分:1)

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

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) 

这样做的好处还在于您的数据不会受到影响。

答案 2 :(得分:1)

这是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

答案 3 :(得分:0)

而不是使用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]