【问题标题】:Building block matrix from array in the correct order以正确的顺序从数组构建块矩阵
【发布时间】:2014-06-05 02:35:30
【问题描述】:

我有一个类似这样的 numpy 数组:

a = np.arange(0,100).reshape(25,4)
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23],
       [24, 25, 26, 27],
       [28, 29, 30, 31],
       [32, 33, 34, 35],
       [36, 37, 38, 39],
       [40, 41, 42, 43],
       [44, 45, 46, 47],
       [48, 49, 50, 51],
       [52, 53, 54, 55],
       [56, 57, 58, 59],
       [60, 61, 62, 63],
       [64, 65, 66, 67],
       [68, 69, 70, 71],
       [72, 73, 74, 75],
       [76, 77, 78, 79],
       [80, 81, 82, 83],
       [84, 85, 86, 87],
       [88, 89, 90, 91],
       [92, 93, 94, 95],
       [96, 97, 98, 99]])

我想使用这个数组以非常精确的顺序创建一个块矩阵。每个块必须是从 a 的相应列构造的方阵。因此,在这种情况下,我们有 4 个 5X5 块。一种方法如下:

a = np.arange(0,100).reshape(25,4)
A = a[:, 0].reshape(np.sqrt(a.shape[0]), np.sqrt(a.shape[0]))
B = a[:, 1].reshape(np.sqrt(a.shape[0]), np.sqrt(a.shape[0]))
C = a[:, 2].reshape(np.sqrt(a.shape[0]), np.sqrt(a.shape[0]))
D = a[:, 3].reshape(np.sqrt(a.shape[0]), np.sqrt(a.shape[0]))

np.bmat([[A,B],[C,D]])

matrix([[ 0,  4,  8, 12, 16,| 1,  5,  9,  13, 17],
        [20, 24, 28, 32, 36,| 21, 25, 29, 33, 37],
        [40, 44, 48, 52, 56,| 41, 45, 49, 53, 57],
        [60, 64, 68, 72, 76,| 61, 65, 69, 73, 77],
        [80, 84, 88, 92, 96,| 81, 85, 89, 93, 97],
         --------------------------------------- ,
        [ 2,  6, 10, 14, 18,| 3,  7,  11, 15, 19],
        [22, 26, 30, 34, 38,| 23, 27, 31, 35, 39],
        [42, 46, 50, 54, 58,| 43, 47, 51, 55, 59],
        [62, 66, 70, 74, 78,| 63, 67, 71, 75, 79],
        [82, 86, 90, 94, 98,| 83, 87, 91, 95, 99]])

但是,我需要在不“手动”创建每个矩阵的情况下构建此矩阵,并且能够将此方法推广到更多维度(3X3、4X4 等)

谢谢!

【问题讨论】:

    标签: python arrays numpy matrix


    【解决方案1】:

    作为(长)单班轮:

    In [14]: a = np.arange(0,100).reshape(25,4)
    
    In [15]: a.T.reshape(2, 2, 5, 5).transpose(0, 2, 1, 3).reshape(10, 10)
    Out[15]:
    array([[ 0,  4,  8, 12, 16,  1,  5,  9, 13, 17],
           [20, 24, 28, 32, 36, 21, 25, 29, 33, 37],
           [40, 44, 48, 52, 56, 41, 45, 49, 53, 57],
           [60, 64, 68, 72, 76, 61, 65, 69, 73, 77],
           [80, 84, 88, 92, 96, 81, 85, 89, 93, 97],
           [ 2,  6, 10, 14, 18,  3,  7, 11, 15, 19],
           [22, 26, 30, 34, 38, 23, 27, 31, 35, 39],
           [42, 46, 50, 54, 58, 43, 47, 51, 55, 59],
           [62, 66, 70, 74, 78, 63, 67, 71, 75, 79],
           [82, 86, 90, 94, 98, 83, 87, 91, 95, 99]])
    

    如果相关,请注意最后一次整形会触发副本,所以你得到的是一个新数组,而不是旧数组的视图。

    对于一般情况,如果你有 mxn 形状块 pxq 你可以这样做:

    In [24]: m = 4; n = 2; p = 3; q = 5
    
    In [25]: a = np.arange(m*n*p*q).reshape(p*q, m*n)
    
    In [26]: a.T.reshape(m, n, p, q).transpose(0, 2, 1, 3).reshape(m*p, n*q)
    Out[26]:
    array([[  0,   8,  16,  24,  32,   1,   9,  17,  25,  33],
           [ 40,  48,  56,  64,  72,  41,  49,  57,  65,  73],
           [ 80,  88,  96, 104, 112,  81,  89,  97, 105, 113],
           [  2,  10,  18,  26,  34,   3,  11,  19,  27,  35],
           [ 42,  50,  58,  66,  74,  43,  51,  59,  67,  75],
           [ 82,  90,  98, 106, 114,  83,  91,  99, 107, 115],
           [  4,  12,  20,  28,  36,   5,  13,  21,  29,  37],
           [ 44,  52,  60,  68,  76,  45,  53,  61,  69,  77],
           [ 84,  92, 100, 108, 116,  85,  93, 101, 109, 117],
           [  6,  14,  22,  30,  38,   7,  15,  23,  31,  39],
           [ 46,  54,  62,  70,  78,  47,  55,  63,  71,  79],
           [ 86,  94, 102, 110, 118,  87,  95, 103, 111, 119]])
    

    【讨论】:

    • 美丽的答案。你是怎么想出这个解决方案的?我不太明白为什么 reshape 具有分区数组的这种效果。似乎您的代码基本上是在说“我想要 2 个数组,并且每个数组都必须有 2 个尺寸为 5X5 的数组”另一个问题:为什么最后一个 reshape 会产生一个副本,而不是第一个?
    • 第一个 reshape 创建 4 个块,transpose 重新排列它们,最后 reshape 将它们连接回 2D 数组。因为 ndarray 数据存储在单个连续的内存块中,所以最后一次整形需要移动数据,而不仅仅是改变查看方式。来自文档的This 可能有助于理解它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    相关资源
    最近更新 更多