Python:如何将任意数量的小矩阵动态组合成一个大矩阵

Python:如何将任意数量的小矩阵动态组合成一个大矩阵,python,numpy,matrix,Python,Numpy,Matrix,我有这4个矩阵,我想通过传递n:小矩阵的数量和输出矩阵的行和列,动态地将它们组合成一个大矩阵 例如: 输出矩阵: [[ 1 2 5 6] [ 3 4 7 8] [ 9 10 13 14] [11 12 15 16]] 我可以使用以下工具手动执行此操作: M = np.bmat( [[x1], [x2], [x3], [x4]] ) 2分钟实施(对于编辑前的问题,可能对某人有用): 如果阵列的大小很大,则有改进的余地…2分钟的实施时间(对于编辑前的问题,可能对某些人有用):

我有这4个矩阵,我想通过传递n:小矩阵的数量和输出矩阵的行和列,动态地将它们组合成一个大矩阵 例如:

输出矩阵:

[[ 1  2  5  6]
 [ 3  4  7  8]
 [ 9 10 13 14]
 [11 12 15 16]]
我可以使用以下工具手动执行此操作:

M = np.bmat( [[x1], [x2], [x3], [x4]] )
2分钟实施(对于编辑前的问题,可能对某人有用):

如果阵列的大小很大,则有改进的余地…

2分钟的实施时间(对于编辑前的问题,可能对某些人有用):

如果数组的大小很大,那么还有改进的余地……

我认为(但不知道它是否正确),最好是原地工作,避免每次都用新方法创建新对象,特别是在循环中多次创建时。这些示例仅适用于二维矩阵。但它可以很容易地实现到更多维度。最好是有一个大数组,如果它真的很大的话,用numpy.memmap数组。然后在它的部分工作。最快的索引(仅次于指针)将出现在cython MemoryView上

import numpy as np

def combine_matrix(*args):  
    n=len(args)
    rows,cols=args[0].shape
    a=np.zeros((n,cols*rows))
    m=0
    for i in range(n/rows):
        for j in range(n/cols):
            a[i*rows:(i+1)*rows,j*cols:(j+1)*cols]=args[m]
            m+=1

    return a

def example1():
    print '#'*10
    a=np.arange(1,17)

    n=4
    rows,cols=n/2,n/2

    lst=[]
    for i in range(n):
        ai=a[i*n:(i+1)*n]
        ai.shape=rows,cols
        lst.append(ai)

    print lst
    print combine_matrix(*lst)

def example2():
    print '#'*10
    m=24
    a=np.arange(m)

    n=6
    rows,cols=m/n/2,n/2

    lst=[]
    for i in range(m/n):
        ai=a[i*n:(i+1)*n]
        ai.shape=rows,cols
        lst.append(ai)

    print lst
    print combine_matrix(*lst)

def example3():
    print '#'*10
    m,n=36,6
    a=np.arange(m)

    arrs=np.array_split(a,n)
    for i in range(n):
        ln=arrs[i].shape[0]
        arrs[i].shape=2,ln/2

    print combine_matrix(*arrs) 

example1()
example2()
example3()
我认为(但不知道是否正确),最好是原地工作,避免每次都用新方法创建新对象,特别是在循环中多次创建新对象时。这些示例仅适用于二维矩阵。但它可以很容易地实现到更多维度。最好是有一个大数组,如果它真的很大的话,用numpy.memmap数组。然后在它的部分工作。最快的索引(仅次于指针)将出现在cython MemoryView上

import numpy as np

def combine_matrix(*args):  
    n=len(args)
    rows,cols=args[0].shape
    a=np.zeros((n,cols*rows))
    m=0
    for i in range(n/rows):
        for j in range(n/cols):
            a[i*rows:(i+1)*rows,j*cols:(j+1)*cols]=args[m]
            m+=1

    return a

def example1():
    print '#'*10
    a=np.arange(1,17)

    n=4
    rows,cols=n/2,n/2

    lst=[]
    for i in range(n):
        ai=a[i*n:(i+1)*n]
        ai.shape=rows,cols
        lst.append(ai)

    print lst
    print combine_matrix(*lst)

def example2():
    print '#'*10
    m=24
    a=np.arange(m)

    n=6
    rows,cols=m/n/2,n/2

    lst=[]
    for i in range(m/n):
        ai=a[i*n:(i+1)*n]
        ai.shape=rows,cols
        lst.append(ai)

    print lst
    print combine_matrix(*lst)

def example3():
    print '#'*10
    m,n=36,6
    a=np.arange(m)

    arrs=np.array_split(a,n)
    for i in range(n):
        ln=arrs[i].shape[0]
        arrs[i].shape=2,ln/2

    print combine_matrix(*arrs) 

example1()
example2()
example3()

[编辑-我假设小数组是独立创建的,尽管我的示例是基于拆分(4,2,2)数组。如果它们实际上只是3d数组的平面,则“重塑”和“转置”的组合会更好。但即使这样的解决方案也会生成副本,因为原始值已重新排列。]

让我们列出2x2阵列(此处来自3d阵列)。需要挤压,因为此拆分生成(1,2,2)阵列:

您的
bmat
方法-已更正以生成方形排列

In [333]: np.bmat([[xl[0],xl[1]],[xl[2],xl[3]]])
Out[333]: 
matrix([[ 1,  2,  5,  6],
        [ 3,  4,  7,  8],
        [ 9, 10, 13, 14],
        [11, 12, 15, 16]])
串联方法:

In [334]: np.vstack([np.hstack(xl[:2]),np.hstack(xl[2:])])
Out[334]: 
array([[ 1,  2,  5,  6],
       [ 3,  4,  7,  8],
       [ 9, 10, 13, 14],
       [11, 12, 15, 16]])
由于切片在
hstack
中工作,我也可以在
bmat
中使用它:

In [335]: np.bmat([xl[:2],xl[2:]])
Out[335]: 
matrix([[ 1,  2,  5,  6],
        [ 3,  4,  7,  8],
        [ 9, 10, 13, 14],
        [11, 12, 15, 16]])
内部
bmat
(检查其代码)正在使用
hstack
vstack
版本(第一个和最后一个轴上的ContactEnables)。有效地

In [366]: ll=[xl[:2], xl[2:]]

In [367]: np.vstack([np.hstack(row) for row in ll])
Out[367]: 
array([[ 1,  2,  5,  6],
       [ 3,  4,  7,  8],
       [ 9, 10, 13, 14],
       [11, 12, 15, 16]])
您必须如何指定这些
n
数组的排列
np.bmat(xl)
生成一个
(2,8)
矩阵(
hstack
)<代码>np.vstack(xl)生成一个
(8,2)
数组

将其扩展到3x3、2x3等子阵列布局应该不难
xl
是子阵列的列表。将其重新加工为所需的子阵列列表,并应用
bmat
堆栈的组合


2个2x3布局的快速版本(4d
xl
阵列比2x3嵌套列表更容易构建,但功能相同:

In [369]: xl=np.arange(3*2*2*2).reshape((3,2,2,2))

In [370]: np.vstack([np.hstack(row) for row in xl])
Out[370]: 
array([[ 0,  1,  4,  5],
       [ 2,  3,  6,  7],
       [ 8,  9, 12, 13],
       [10, 11, 14, 15],
       [16, 17, 20, 21],
       [18, 19, 22, 23]])

In [371]: xl=np.arange(2*3*2*2).reshape((2,3,2,2))

In [372]: np.vstack([np.hstack(row) for row in xl])
Out[372]: 
array([[ 0,  1,  4,  5,  8,  9],
       [ 2,  3,  6,  7, 10, 11],
       [12, 13, 16, 17, 20, 21],
       [14, 15, 18, 19, 22, 23]])

[编辑-我假设小数组是独立创建的,尽管我的示例是基于拆分(4,2,2)数组。如果它们实际上只是3d数组的平面,则“重塑”和“转置”的组合会更好。但即使这样的解决方案也会生成副本,因为原始值已重新排列。]

让我们列出2x2阵列(此处来自3d阵列)。需要挤压,因为此拆分会生成(1,2,2)阵列:

您的
bmat
方法-已更正以生成方形排列

In [333]: np.bmat([[xl[0],xl[1]],[xl[2],xl[3]]])
Out[333]: 
matrix([[ 1,  2,  5,  6],
        [ 3,  4,  7,  8],
        [ 9, 10, 13, 14],
        [11, 12, 15, 16]])
串联方法:

In [334]: np.vstack([np.hstack(xl[:2]),np.hstack(xl[2:])])
Out[334]: 
array([[ 1,  2,  5,  6],
       [ 3,  4,  7,  8],
       [ 9, 10, 13, 14],
       [11, 12, 15, 16]])
由于切片在
hstack
中工作,我也可以在
bmat
中使用它:

In [335]: np.bmat([xl[:2],xl[2:]])
Out[335]: 
matrix([[ 1,  2,  5,  6],
        [ 3,  4,  7,  8],
        [ 9, 10, 13, 14],
        [11, 12, 15, 16]])
内部
bmat
(检查其代码)正在使用
hstack
vstack
版本(第一轴和最后一轴上的触点)。有效

In [366]: ll=[xl[:2], xl[2:]]

In [367]: np.vstack([np.hstack(row) for row in ll])
Out[367]: 
array([[ 1,  2,  5,  6],
       [ 3,  4,  7,  8],
       [ 9, 10, 13, 14],
       [11, 12, 15, 16]])
您必须如何指定这些
n
数组的排列。
np.bmat(xl)
生成
(2,8)
矩阵(
hstack
)。
np.vstack(xl)
生成
(8,2)
数组

将其扩展到3x3、2x3等子阵列布局应该不难。
xl
是子阵列列表。将其重新编辑为所需的子阵列列表,并应用
bmat
堆栈的组合


2个2x3布局的快速版本(4d
xl
阵列比2x3嵌套列表更容易构建,但功能相同:

In [369]: xl=np.arange(3*2*2*2).reshape((3,2,2,2))

In [370]: np.vstack([np.hstack(row) for row in xl])
Out[370]: 
array([[ 0,  1,  4,  5],
       [ 2,  3,  6,  7],
       [ 8,  9, 12, 13],
       [10, 11, 14, 15],
       [16, 17, 20, 21],
       [18, 19, 22, 23]])

In [371]: xl=np.arange(2*3*2*2).reshape((2,3,2,2))

In [372]: np.vstack([np.hstack(row) for row in xl])
Out[372]: 
array([[ 0,  1,  4,  5,  8,  9],
       [ 2,  3,  6,  7, 10, 11],
       [12, 13, 16, 17, 20, 21],
       [14, 15, 18, 19, 22, 23]])

您可以将换位和重塑操作结合起来:

In [1878]: x=arange(24).reshape(4,3,2)

In [1879]: (_,n,m)=x.shape

In [1880]: x.reshape(2,2,n,m).transpose(0,2,1,3).reshape(2*n,2*m)
Out[1880]: 
array([[ 0,  1,  6,  7],
       [ 2,  3,  8,  9],
       [ 4,  5, 10, 11],
       [12, 13, 18, 19],
       [14, 15, 20, 21],
       [16, 17, 22, 23]])

您可以将换位和重塑操作结合起来:

In [1878]: x=arange(24).reshape(4,3,2)

In [1879]: (_,n,m)=x.shape

In [1880]: x.reshape(2,2,n,m).transpose(0,2,1,3).reshape(2*n,2*m)
Out[1880]: 
array([[ 0,  1,  6,  7],
       [ 2,  3,  8,  9],
       [ 4,  5, 10, 11],
       [12, 13, 18, 19],
       [14, 15, 20, 21],
       [16, 17, 22, 23]])

如果你想知道bmat是如何工作的,你需要澄清这些小数组是单独创建的,还是只是3d数组的平面。你是从(4,2,2)数组开始,然后将其转换成(4,4)数组吗数组,或者从4个单独的数组开始。你对
bmat
没有提供的数组有什么要求?如果你想知道bmat是如何工作的,你需要澄清这些小数组是单独创建的,还是它们只是3d数组的平面。你是从(4,2,2)数组开始并将其转换为(4,4)数组吗数组,或从4个单独的数组开始。anserw用于在新anserw中编辑;转储我的2分钟解决方案xDanserw用于在新anserw中编辑是浪费;转储我的2分钟解决方案xDanserw是浪费。如果每次创建新列表并使用方法,我不喜欢它。在cython MemoryView上,更快的解决方案不是就位了吗?您的答案是t像
串联
,除了你的操作在两个轴上。如果用c或cython编码,你的可以在我重复的堆栈上节省时间。列表副本没有什么大不了的,因为它们只是复制对象指针。如果原始数组还没有占用