没有fill_diagonal的inf的Python矩阵对角线 [英] Python matrix diagonal of inf without fill_diagonal

查看:136
本文介绍了没有fill_diagonal的inf的Python矩阵对角线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将矩阵的对角元素设置为Inf.

一种简单的方法是使用np.fill_diagonal.

np.fill_diagonal(my_matrix, float('inf')

但是fill_diagonal修改输入矩阵,而不是返回填充对角线的新矩阵. 这对我不起作用.我需要在不修改原始矩阵的情况下填充对角线.

当然我可以克隆原始矩阵,所以我将始终保留原始矩阵的副本.但是,我不太喜欢这种解决方案,因为我会经常更新原始矩阵,因此每次需要对角线为inf时,都必须对其进行复制.

是否有一个功能与fill_diagonal相同但不修改输入矩阵?像这样:

new_matrix = np.fill_diagonal(original_matrix, float('inf') 

为什么我需要这个:

我的矩阵是点之间的距离矩阵,我想在每一步中计算两个最近的点.当然,此矩阵的对角线为0(因为从点到自身的距离为0).因此,要确保我不会接受相同的观点,我的解决方案是将对角线设置为Inf.

但是,一旦找到两个点,我需要计算这两个点与其余点之间的平均距离,因此我实际上需要对角线为0而不是Inf.

当前我正在做的是

  • 用Inf填充对角线
  • 找到2个最接近的点
  • 用0填充对角线
  • 计算这两个点之间以及其余两个点之间的平均距离.

    # fill diagonal with Inf to avoid taking the diagonals
    np.fill_diagonal(data, float('inf'))  
    # find the minimum distance
    idx = np.argmin(data)
    # fill the diagonals back to 0
    np.fill_diagonal(data, 0.0) 
    # get the coordinates of the minimum distance
    row, col =  np.unravel_index(idx,data.shape)
    # compute the new node as the average distance between the two points
    new_node = np.mean((data[:,row],data[:,col]),0)
    # replace the first node (row) with the new node
    data[:,row] = new_node
    data[row,:] = new_node.T
    # delete the second node (col) from the matrix
    data = np.delete(data, col, 0)  # delete row
    data = np.delete(data, col, 1)  # delete column
    

但是,我不喜欢将对角线设置为Inf然后返回0的想法,我宁愿仅将函数传递给argmax,该函数返回用Inf填充对角线的数据,而无需实际修改矩阵数据.

类似的东西:

idx = np.argmin(return_filled_diagonals(data, float('Inf'))
# here I can operate with data as usual since it has not been modified.

解决方案

orig_mat = np.array([[1.2,2,3],[4,5,6],[7,8,9]])

#set diagonal to inf without making a copy of the array.
orig_mat + np.where(np.eye(orig_mat.shape[0])>0,np.inf,0)
array([[ inf,   2.,   3.],
       [  4.,  inf,   6.],
       [  7.,   8.,  inf]])

#the original array remains untorched.
print(orig_mat)
[[ 1.2  2.   3. ]
 [ 4.   5.   6. ]
 [ 7.   8.   9. ]]

I need to set the diagonal elements of a matrix to Inf.

An easy way to do it is to use np.fill_diagonal.

np.fill_diagonal(my_matrix, float('inf')

However fill_diagonal modifies the input matrix instead of returning a new matrix with the diagonal filled. This doesn't work for me. I need the diagonals filled WITHOUT modifying the original matrix.

Of course I could clone the original matrix, so I will always keep a copy of the original matrix. However I don't really like this solution, since I will update my original matrix often and therefore I'll have to make copies of it every time I need the diagonal to be inf.

Is there a function that will do the same that fill_diagonal but without modifying the input matrix? Something like:

new_matrix = np.fill_diagonal(original_matrix, float('inf') 

Why I need this:

My matrix is a distance matrix between points and I want to compute at each step the two closest points. Of course the diagonal of this matrix is 0 (since the distance from a point to itself is 0). So my solution to make sure I don't take the same point is to set the diagonals to Inf.

However once the two points are found, I need to compute the average of the distances between this two points and the rest of the points, so I actually need the diagonals to be 0 instead of Inf.

Currently what I'm doing is:

  • Fill diagonals with Inf
  • Find the 2 closest points
  • Fill diagonals with 0
  • Compute the average distance between this two points and the rest of them.

    # fill diagonal with Inf to avoid taking the diagonals
    np.fill_diagonal(data, float('inf'))  
    # find the minimum distance
    idx = np.argmin(data)
    # fill the diagonals back to 0
    np.fill_diagonal(data, 0.0) 
    # get the coordinates of the minimum distance
    row, col =  np.unravel_index(idx,data.shape)
    # compute the new node as the average distance between the two points
    new_node = np.mean((data[:,row],data[:,col]),0)
    # replace the first node (row) with the new node
    data[:,row] = new_node
    data[row,:] = new_node.T
    # delete the second node (col) from the matrix
    data = np.delete(data, col, 0)  # delete row
    data = np.delete(data, col, 1)  # delete column
    

However I don't like the idea of setting diagonals to Inf and then back to 0, I would prefer just passing a function to argmax that returns data with diagonal filled with Inf without actually modifying the matrix data.

Something like:

idx = np.argmin(return_filled_diagonals(data, float('Inf'))
# here I can operate with data as usual since it has not been modified.

解决方案

orig_mat = np.array([[1.2,2,3],[4,5,6],[7,8,9]])

#set diagonal to inf without making a copy of the array.
orig_mat + np.where(np.eye(orig_mat.shape[0])>0,np.inf,0)
array([[ inf,   2.,   3.],
       [  4.,  inf,   6.],
       [  7.,   8.,  inf]])

#the original array remains untorched.
print(orig_mat)
[[ 1.2  2.   3. ]
 [ 4.   5.   6. ]
 [ 7.   8.   9. ]]

这篇关于没有fill_diagonal的inf的Python矩阵对角线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆