Python 从较小的矩阵填充较大的矩阵

Python 从较小的矩阵填充较大的矩阵,python,arrays,numpy,matrix,Python,Arrays,Numpy,Matrix,我必须用较小的2D数组生成的块填充较大的2D数组,但仍然要考虑比新的大2D数组边缘的块宽度更小的列行数。例如,使用3x3块从左侧阵列创建右侧阵列 [[ 1 2 3 4] [[ 1. 1. 1. 2. 2. 2. 3. 3. 3. 4. 4.] [ 5 6 7 8] -> [ 1. 1. 1. 2. 2. 2. 3. 3. 3. 4. 4.] [ 9 10 11 1

我必须用较小的2D数组生成的块填充较大的2D数组,但仍然要考虑比新的大2D数组边缘的块宽度更小的列行数。例如,使用3x3块从左侧阵列创建右侧阵列

[[ 1  2  3  4]         [[  1.   1.   1.   2.   2.   2.   3.   3.   3.   4.   4.]
 [ 5  6  7  8]    ->    [  1.   1.   1.   2.   2.   2.   3.   3.   3.   4.   4.]
 [ 9 10 11 12]]         [  1.   1.   1.   2.   2.   2.   3.   3.   3.   4.   4.]
                        [  5.   5.   5.   6.   6.   6.   7.   7.   7.   8.   8.]
                        [  5.   5.   5.   6.   6.   6.   7.   7.   7.   8.   8.]
                        [  5.   5.   5.   6.   6.   6.   7.   7.   7.   8.   8.]
                        [  9.   9.   9.  10.  10.  10.  11.  11.  11.  12.  12.]]
我实现了如下所示,但我正在寻找一种更聪明的方法

# Smaller array
a=np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])

# The size of the blocks for filling in the matrix
blockSize = 3

# The number of columns and rows of the new matrix (b)
cols = 11
rows = 7
b = np.zeros([rows, cols])

for i in range(0, rows, blockSize):
    ii = i/blockSize
    if i + blockSize < rows:
        numRows = blockSize
    else:
        numRows = rows - i
    for j in range(0, cols, blockSize):
        jj= j/blockSize
        if j + blockSize < cols:
            numCols = blockSize
        else:
            numCols = cols - j

        b[i:i+numRows,j:j+numCols] = a[ii,jj]
#更小的数组
a=np.数组([[1,2,3,4],[5,6,7,8],[9,10,11,12])
#用于填充矩阵的块的大小
块大小=3
#新矩阵的列数和行数(b)
cols=11
行=7
b=np.零([行,列])
对于范围内的i(0,行,块大小):
ii=i/块大小
如果i+块大小<行:
numRows=块大小
其他:
numRows=行-i
对于范围内的j(0,cols,blockSize):
jj=j/块大小
如果j+块大小
您可以使用
np.重复
来重复矩阵,然后使用简单的切片来删除多余的行,
np.删除
来删除列

因此,作为一种更通用的方法,您可以使用以下函数:

>>> def array_crator(arr,new_shape):
...       repeat_dims=np.divide(new_shape,arr.shape)+1
...       return np.delete(a.repeat(repeat_dims[1],axis=1).repeat(repeat_dims[0],axis=0),np.s_[new_shape[1]:],1)[:new_shape[0]]
演示:

另一个例子:

>>> a=np.arange(2,22).reshape(4,5)
>>> a
array([[ 2,  3,  4,  5,  6],
       [ 7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16],
       [17, 18, 19, 20, 21]])
>>> array_crator(a,(7,11))
array([[ 2,  2,  2,  3,  3,  3,  4,  4,  4,  5,  5],
       [ 2,  2,  2,  3,  3,  3,  4,  4,  4,  5,  5],
       [ 7,  7,  7,  8,  8,  8,  9,  9,  9, 10, 10],
       [ 7,  7,  7,  8,  8,  8,  9,  9,  9, 10, 10],
       [12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15],
       [12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15],
       [17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20]])
>>> array_crator(a,(9,17))
array([[ 2,  2,  2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  5,  5,  5,  5,  6],
       [ 2,  2,  2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  5,  5,  5,  5,  6],
       [ 2,  2,  2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  5,  5,  5,  5,  6],
       [ 7,  7,  7,  7,  8,  8,  8,  8,  9,  9,  9,  9, 10, 10, 10, 10, 11],
       [ 7,  7,  7,  7,  8,  8,  8,  8,  9,  9,  9,  9, 10, 10, 10, 10, 11],
       [ 7,  7,  7,  7,  8,  8,  8,  8,  9,  9,  9,  9, 10, 10, 10, 10, 11],
       [12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16],
       [12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16],
       [12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16]])

你可以分两个阶段重复;一次用于列,一次用于行

a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
blockSize = 3
cols = 11
rows = 7
每次,根据
块大小
计算每个元素的重复次数列表(例如,
[3,3,2]
)。这将创建所需大小的数组:

>>> result = a.repeat([blockSize]*(cols//blockSize) + [cols % blockSize], axis=1)
>>> result = result.repeat([blockSize]*(rows//blockSize) + [rows % blockSize], axis=0)
>>> result
array([[ 1,  1,  1,  2,  2,  2,  3,  3,  3,  4,  4],
       [ 1,  1,  1,  2,  2,  2,  3,  3,  3,  4,  4],
       [ 1,  1,  1,  2,  2,  2,  3,  3,  3,  4,  4],
       [ 5,  5,  5,  6,  6,  6,  7,  7,  7,  8,  8],
       [ 5,  5,  5,  6,  6,  6,  7,  7,  7,  8,  8],
       [ 5,  5,  5,  6,  6,  6,  7,  7,  7,  8,  8],
       [ 9,  9,  9, 10, 10, 10, 11, 11, 11, 12, 12]])

另一种方法是使用
np.kron
创建每个元素的块,然后将数组切片到所需大小。但是,这会首先创建一个数组,该数组可能比所需的大得多(并且可能内存不足)


我喜欢@acjr的答案,但这里有另一种方法,使用scikit image的漂亮功能

将numpy导入为np
进口撇渣
a=np.数组([[1,2,3,4],[5,6,7,8],[9,10,11,12])
#创建输出数组(包括稍后将修剪的列)
结果=np.零((9,12))
#创建一个可通过平铺索引寻址的特殊视图
#此视图可以按如下方式编制索引:
#结果作为分片[分片索引分片索引分片索引分片索引分片索引分片索引分片索引分片索引分片索引分片索引分片索引分片索引分片索引
结果作为块=skimage.util.view作为块(结果,(3,3))
将结果_断言为_tiles.shape==(3,3)+a.shape
#现在使用简单的广播来分配每个元素
#将您的输入矩阵转换为输出的整个平铺
结果_as_tiles[:]=a[:,:,np.newaxis,np.newaxis]
#最后,切掉不需要的行/列
修剪结果=结果[:7,:11]
打印结果
印刷品:

[[  1.   1.   1.   2.   2.   2.   3.   3.   3.   4.   4.]
 [  1.   1.   1.   2.   2.   2.   3.   3.   3.   4.   4.]
 [  1.   1.   1.   2.   2.   2.   3.   3.   3.   4.   4.]
 [  5.   5.   5.   6.   6.   6.   7.   7.   7.   8.   8.]
 [  5.   5.   5.   6.   6.   6.   7.   7.   7.   8.   8.]
 [  5.   5.   5.   6.   6.   6.   7.   7.   7.   8.   8.]
 [  9.   9.   9.  10.  10.  10.  11.  11.  11.  12.  12.]]

每行有12个元素,而不是11@franciscod的确,我错过了,谢谢提醒!您需要的是一个众所周知的数学运算:它是用numpy实现的:请参阅
np.kron(a, np.ones((blockSize, blockSize)))[:rows, :cols]
[[  1.   1.   1.   2.   2.   2.   3.   3.   3.   4.   4.]
 [  1.   1.   1.   2.   2.   2.   3.   3.   3.   4.   4.]
 [  1.   1.   1.   2.   2.   2.   3.   3.   3.   4.   4.]
 [  5.   5.   5.   6.   6.   6.   7.   7.   7.   8.   8.]
 [  5.   5.   5.   6.   6.   6.   7.   7.   7.   8.   8.]
 [  5.   5.   5.   6.   6.   6.   7.   7.   7.   8.   8.]
 [  9.   9.   9.  10.  10.  10.  11.  11.  11.  12.  12.]]