NumPy:查找子矩阵/块中的最小值以及相应的行,列索引

时间:2016-10-26 15:27:26

标签: python numpy matrix

给定一个方矩阵M(mxm),由维(nxn)的子矩阵组成,其中mxm modulo nxn == 0,返回每个子矩阵的所有最小值的矩阵。

e.g。 M:(4x4)

M = array([[19834, 29333, 29333, 33120],
           [ 5148, 25560, 29393,  8083],
           [ 5148, 29393, 25560,  8083],
           [19958, 25748, 25748, 24506]], dtype=uint64)

每个子矩阵m为2x2,最小值返回如下:

M* = array([[ 5148, 8083],
            [ 5148, 8083]], dtype=uint64)

我试图重新整形数组并调用min(),但它只允许你跨越一个轴。

另外我也希望获得最小值的原始索引,但是我假设我必须在生成M *后搜索它。

2 个答案:

答案 0 :(得分:3)

您可以将两个轴分成另外两个,从而生成一个4D数组,其长度为2,作为这两个分割轴中的第二个,这将是第二个和第四个轴。生成的4D数组。然后,只需沿着这两个轴找到minimum以获得所需的输出。

因此,实现看起来像这样 -

m,n = M.shape
out = M.reshape(m//2,2,n//2,2).min(axis=(1,3))

示例运行 -

In [41]: M
Out[41]: 
array([[33, 26, 15, 53, 72, 53],
       [12, 64, 28, 27, 58, 51],
       [61, 42, 70, 92, 61, 95],
       [35, 62, 48, 27, 53, 33]])

In [42]: m,n = M.shape

In [43]: M.reshape(m//2,2,n//2,2).min(axis=(1,3))
Out[43]: 
array([[12, 15, 51],
       [35, 27, 33]])

在与原始数组相对应的每个子矩阵中获取argmins

为了获得这些argmins,我们需要做一些额外的工作,如下所示 -

B = 2 # Blocksize 
m,n = M.shape

# Reshape into 4D array as discussed for the previous problem
M4D = M.reshape(m//B,B,n//B,B)

# Bring the second and fourth axes together and then merge.
# Then, get linear indices within each submatrix
lidx = M4D.transpose(0,2,1,3).reshape(-1,n//B,B**2).argmin(-1)

# Convert those linear indices into row, col indices corresponding
# to submatrix and finally corresponding to the original array
r,c = np.unravel_index(lidx,[B,B])
row = r + (B*np.arange(m//B)[:,None])
col = c + B*np.arange(n//B)

示例输入,输出 -

In [170]: M
Out[170]: 
array([[40, 91, 90, 72, 86, 44],
       [63, 56, 20, 95, 60, 41],
       [28, 50, 32, 89, 69, 46],
       [41, 41, 33, 81, 30, 63]])

In [171]: np.column_stack((row.ravel(),col.ravel()))
Out[171]: 
array([[0, 0],
       [1, 2],
       [1, 5],
       [2, 0],
       [2, 2],
       [3, 4]])

答案 1 :(得分:0)

我认为这可能会使用np.hsplitnp.vsplit

由于python3中的map返回map object,因此有必要在进一步计算之前对地图的结果进行分类。

修改:对于第二个问题,将np.min更改为np.argmin会产生一个位置矩阵。

import numpy as np

M_star = np.array(list(map(lambda x: list(map(lambda x: np.min(x), x)), list(map(lambda x: np.hsplit(x, n), np.vsplit(M, n))))))
M_star_pos = np.array(list(map(lambda x: list(map(lambda x: np.argmin(x), x)), list(map(lambda x: np.hsplit(x, n), np.vsplit(M, n))))))