首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >不含fill_diagonal的inf的Python矩阵对角

不含fill_diagonal的inf的Python矩阵对角
EN

Stack Overflow用户
提问于 2017-05-03 11:36:41
回答 4查看 1.6K关注 0票数 1

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

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

代码语言:javascript
运行
复制
np.fill_diagonal(my_matrix, float('inf')

但是,fill_diagonal修改输入矩阵,而不是返回对角填充的新矩阵。这对我不管用。我需要填充对角线而不修改原始矩阵。

当然,我可以克隆原始矩阵,所以我总是保留原始矩阵的副本。然而,我并不真的喜欢这个解决方案,因为我将经常更新我的原始矩阵,因此,我将不得不复制它,每次我需要对角是inf。

是否有一个函数可以执行与fill_diagonal相同的操作,但不修改输入矩阵?类似于:

代码语言:javascript
运行
复制
new_matrix = np.fill_diagonal(original_matrix, float('inf') 

为什么我需要这个:

我的矩阵是点之间的距离矩阵,我想在每一步计算两个最近的点。当然,这个矩阵的对角线是0(因为从一个点到它本身的距离是0)。因此,我的解决方案,以确保我不采取相同的一点,是设置对角为Inf。

然而,一旦找到这两个点,我需要计算这两个点与其余点之间距离的平均值,所以我实际上需要对角值为0而不是Inf。

目前我所做的是:

  • 用Inf填充对角线
  • 找到两个最近的点
  • 用0填充对角线
  • 用Inf计算这两点与them.fill对角线其余部分之间的平均距离,以避免取对角线np.fill_diagonal(数据,浮点(‘inf’))#查找最小距离idx =np.argmin(数据)#将对角线填充回0 np.fill_diagonal(数据,0.0) #获取最小距离行的坐标,col = np.unravel_index(idx,data.shape) #计算新节点作为两点之间的平均距离new_node =np.mean(数据:行,数据:,data.shape),#将第一个节点(行)替换为新的节点数据:,row = new_node datarow,:= new_node.T #删除矩阵数据中的第二个节点(col) = np.delete( data,col,0) # delete行数据= np.delete( data,col,1) # delete列

但是,我不喜欢将对角线设置为Inf,然后返回到0,我更喜欢将一个函数传递给argmax,该函数返回带有Inf填充的对角线的数据,而不实际修改矩阵数据。

类似于:

代码语言:javascript
运行
复制
idx = np.argmin(return_filled_diagonals(data, float('Inf'))
# here I can operate with data as usual since it has not been modified.
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-05-03 13:32:40

代码语言:javascript
运行
复制
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. ]]
票数 0
EN

Stack Overflow用户

发布于 2017-05-03 13:47:19

方法#1

您正在寻找的魔术是在NumPy strides中,它可以让我们看到没有对角线元素的数组,因此不再占用内存空间。下面是实现这样一个视图的方法-

代码语言:javascript
运行
复制
def nodiag_view(a):
    m = a.shape[0]
    p,q = a.strides
    return np.lib.stride_tricks.as_strided(a[:,1:], (m-1,m), (p+q,q))

让我们来看看一个样本运行来验证它是一个视图-

代码语言:javascript
运行
复制
In [124]: a  # Input array
Out[124]: 
array([[ 0, 61, 43, 26, 21],
       [20,  0, 78, 29, 64],
       [34, 49,  0, 64, 60],
       [36, 96, 67,  0, 75],
       [36, 85, 40, 74,  0]])

# Get the no-diag view
In [125]: a_nodiag = nodiag_view(a)

# Lets's verify by changing elements in the view and that should change
# elements in the original array too
In [126]: a_nodiag[:] = 999

In [127]: a
Out[127]: 
array([[  0, 999, 999, 999, 999],
       [999,   0, 999, 999, 999],
       [999, 999,   0, 999, 999],
       [999, 999, 999,   0, 999],
       [999, 999, 999, 999,   0]])

最后,让我们看看如何设置它来解决你的整个问题-

代码语言:javascript
运行
复制
def argmin_without_diag(a):
    a_nodiag = nodiag_view(a)
    idx_nodiag = np.argmin(a_nodiag)
    m = a.shape[0]
    idx = idx_nodiag + np.unravel_index(idx_nodiag, (m-1,m))[0]+1
    return  np.unravel_index(idx, a.shape)

样本运行-

代码语言:javascript
运行
复制
In [142]: a
Out[142]: 
array([[ 0, 60, 79, 55, 77],
       [62,  0, 86, 84, 25],
       [32, 96,  0, 74, 89],
       [24, 33, 64,  0, 93],
       [14, 74, 30, 44,  0]])

In [143]: argmin_without_diag(a)
Out[143]: (4, 0)

方法#2

如果您同时考虑内存和性能,可以暂时将对角线设置为infnite,然后获取argmin索引,然后返回原始的对角线值。因此,输入数组实际上是不变的。执行过程会是这样的-

代码语言:javascript
运行
复制
def argmin_without_diag_replacement(a):
    # Store diagonal values
    vals = a.ravel()[::a.shape[1]+1].copy()

    # Set diag ones as infinites
    a.ravel()[::a.shape[1]+1] = np.inf

    # Get argmin index
    idx = np.argmin(a)

    # Put back the original diag values
    a.ravel()[::a.shape[1]+1] = vals
    return np.unravel_index(idx, a.shape)

因此,对于(n x n)形状的数组,临时数组将只有n元素。

样本运行-

代码语言:javascript
运行
复制
In [237]: a
Out[237]: 
array([[  0.,  95.,  57.,  75.,  92.],
       [ 37.,   0.,  69.,  71.,  62.],
       [ 42.,  72.,   0.,  30.,  57.],
       [ 41.,  80.,  94.,   0.,  26.],
       [ 36.,  45.,  71.,  76.,   0.]])

In [238]: argmin_without_diag_replacement(a)
Out[238]: (3, 4)

运行时测试

代码语言:javascript
运行
复制
In [271]: a = np.random.randint(11,99,(1000,1000)).astype(float)

In [272]: np.fill_diagonal(a,0)

In [273]: %timeit argmin_without_diag(a)
1000 loops, best of 3: 1.76 ms per loop

In [274]: %timeit argmin_without_diag_replacement(a)
1000 loops, best of 3: 688 µs per loop
票数 3
EN

Stack Overflow用户

发布于 2017-05-03 11:54:53

据我所知,您希望找到矩阵最小值的索引,但不包括对角线元素:

代码语言:javascript
运行
复制
orig_mat = np.array([[1.2,2,3],[4,5,6],[7,8,9]])
min_idx = np.argmin(orig_mat+np.multiply(np.eye(orig_mat.shape[0]),1e9))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43758949

复制
相关文章

相似问题

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