【问题标题】:Python - Reshape matrix by taking n consecutive rows every n rowsPython - 通过每 n 行取 n 个连续行来重塑矩阵
【发布时间】:2021-05-27 16:27:48
【问题描述】:

在 stackoverflow 上有很多关于使用 NumPy 重塑矩阵的问题。我发现one 与我想要实现的目标密切相关。但是,这个答案对于我的应用程序来说不够通用。所以我们到了。

我有一个包含数百万行的矩阵(形状 m x n),如下所示:

[[0, 0, 0, 0],
 [1, 1, 1, 1],
 [2, 2, 2, 2],
 [3, 3, 3, 3],
 [4, 4, 4, 4],
 [5, 5, 5, 5],
 [6, 6, 6, 6],
 [7, 7, 7, 7],
 [...]]

从这里我想去一个形状m/2 x 2n,就像它可以在下面看到的那样。为此,必须每 n 行取 n 个连续行(在本例中 n = 2)。然后将连续取行的块水平堆叠到未触及的行。在这个例子中,这意味着:

  1. 前两行保持不变。
  2. 获取第 2 行和第 3 行并将它们水平连接到第 0 行和第 1 行。
  3. 将第 6 行和第 7 行水平连接到第 4 行和第 5 行。这个连接的块然后变成第二行和第三行。
  4. ...
[[0, 0, 0, 0, 2, 2, 2, 2],
 [1, 1, 1, 1, 3, 3, 3, 3],
 [4, 4, 4, 4, 6, 6, 6, 6],
 [5, 5, 5, 5, 7, 7, 7, 7],
 [...]]

我如何使用 Numpy 最有效地(就可能的最少计算时间而言)做到这一点?使用 Numba 加快进程是否有意义?还是没有什么可以加快速度的?

【问题讨论】:

  • 请详细说明第二个数组是如何从第一个数组开始计算的,以及它的形状
  • 你现在在做什么没有效率?这更像是一个调试帮助热线,而不是编写/猜测代码!
  • @FBruzzesi:我编辑了我的问题,希望能提供您要求的所有细节。
  • @hpaulj:目前我什么都没做。这就是为什么我问怎么做。我可以想到一种方法,包括一堆 for 循环。但我认为使用Numpy's array manipulation routines 必须有一种更优雅且计算效率更高的方法。对不起,首先是不清楚的代码 sn-ps。我希望更新的更容易理解。

标签: python numpy matrix reshape numba


【解决方案1】:

假设您的数组的长度可以被 4 整除,您可以在创建正确的索引以选择结果数组的“左”和“右”部分的行后使用 numpy.hstack 做到这一点:

import numpy 
# Create the array
N = 1000*4
a = np.hstack([np.arange(0, N)[:, None]]*4) #shape (4000, 4)
a
array([[   0,    0,    0,    0],
       [   1,    1,    1,    1],
       [   2,    2,    2,    2],
       ...,
       [3997, 3997, 3997, 3997],
       [3998, 3998, 3998, 3998],
       [3999, 3999, 3999, 3999]])

left_idx = np.array([np.array([0,1]) + 4*i for i in range(N//4)]).reshape(-1)
right_idx = np.array([np.array([2,3]) + 4*i for i in range(N//4)]).reshape(-1)

r = np.hstack([a[left_idx], a[right_idx]]) #shape (2000, 8)
r
array([[   0,    0,    0, ...,    2,    2,    2],
       [   1,    1,    1, ...,    3,    3,    3],
       [   4,    4,    4, ...,    6,    6,    6],
       ...,
       [3993, 3993, 3993, ..., 3995, 3995, 3995],
       [3996, 3996, 3996, ..., 3998, 3998, 3998],
       [3997, 3997, 3997, ..., 3999, 3999, 3999]])

【讨论】:

  • 谢谢,这行得通。不过,感觉有点慢。这可能是由于r = np.hstack(...) 在内存中分配了新空间。您是否碰巧知道是否有一种方法可以通过仅更改矩阵的view 来实现?这很可能会加快速度。
【解决方案2】:

这是您链接中swapaxes 答案的应用程序。

In [11]: x=np.array([[0, 0, 0, 0],
    ...:  [1, 1, 1, 1],
    ...:  [2, 2, 2, 2],
    ...:  [3, 3, 3, 3],
    ...:  [4, 4, 4, 4],
    ...:  [5, 5, 5, 5],
    ...:  [6, 6, 6, 6],
    ...:  [7, 7, 7, 7]])

通过重塑将数组分成“组”,保持列数 (4) 不变。

In [17]: x.reshape(2,2,2,4)
Out[17]: 
array([[[[0, 0, 0, 0],
         [1, 1, 1, 1]],

        [[2, 2, 2, 2],
         [3, 3, 3, 3]]],


       [[[4, 4, 4, 4],
         [5, 5, 5, 5]],

        [[6, 6, 6, 6],
         [7, 7, 7, 7]]]])

交换两个中间维度,重新组合行:

In [18]: x.reshape(2,2,2,4).transpose(0,2,1,3)
Out[18]: 
array([[[[0, 0, 0, 0],
         [2, 2, 2, 2]],

        [[1, 1, 1, 1],
         [3, 3, 3, 3]]],


       [[[4, 4, 4, 4],
         [6, 6, 6, 6]],

        [[5, 5, 5, 5],
         [7, 7, 7, 7]]]])

然后回到目标形状。最后一步会创建一个原始副本(之前的步骤是view):

In [19]: x.reshape(2,2,2,4).transpose(0,2,1,3).reshape(4,8)
Out[19]: 
array([[0, 0, 0, 0, 2, 2, 2, 2],
       [1, 1, 1, 1, 3, 3, 3, 3],
       [4, 4, 4, 4, 6, 6, 6, 6],
       [5, 5, 5, 5, 7, 7, 7, 7]])

很难一概而论,因为有不同的方式来重新排列块。例如我的第一次尝试产生:

In [16]: x.reshape(4,2,4).transpose(1,0,2).reshape(4,8)
Out[16]: 
array([[0, 0, 0, 0, 2, 2, 2, 2],
       [4, 4, 4, 4, 6, 6, 6, 6],
       [1, 1, 1, 1, 3, 3, 3, 3],
       [5, 5, 5, 5, 7, 7, 7, 7]])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-18
    • 1970-01-01
    • 2011-12-17
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    相关资源
    最近更新 更多