问题描述
在 stackoverflow 上有很多关于使用 NumPy 重构矩阵的问题。我发现 one 与我要实现的目标密切相关。但是,这个答案对于我的应用程序来说不够通用。所以我们来了。
[[0,0],[1,1,1],[2,2,2],[3,3,3],[4,4,4],[5,5,5],[6,6,6],[7,7,7],[...]]
从这里我想去一个形状 m/2 x 2n
就像它可以在下面看到的那样。为此,必须每 n 行取 n 个连续行(在本例中 n = 2)。然后将连续获取的行的块水平堆叠到未触及的行。在这个例子中,这意味着:
- 前两行保持原样。
- 取第 2 行和第 3 行,将它们水平连接到第 0 行和第 1 行。
- 将第 6 行和第 7 行水平连接到第 4 行和第 5 行。这个串联的块然后成为第二行和第三行。
- ...
[[0,[...]]
如何使用 Numpy 最有效地(就可能的计算时间而言)做到这一点?使用 Numba 加快进程是否有意义?还是没有什么可以加速的?
解决方法
假设您的数组的长度可以被 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],[ 1,1,1],[ 2,2,2],...,[3997,3997,3997],[3998,3998,3998],[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,3,3],[ 4,4,6,6],[3993,3993,3995,3995],[3996,3996,3999]])
,
这是您链接中 swapaxes
答案的应用。
In [11]: x=np.array([[0,...: [1,...: [2,...: [3,...: [4,4],...: [5,5,5],...: [6,...: [7,7,7]])
通过重塑将数组分成“组”,保持列数 (4) 不变。
In [17]: x.reshape(2,4)
Out[17]:
array([[[[0,[1,1]],[[2,[3,3]]],[[[4,[5,5]],[[6,[7,7]]]])
交换 2 个中间维度,重新组合行:
In [18]: x.reshape(2,4).transpose(0,3)
Out[18]:
array([[[[0,[2,2]],[[1,[6,6]],[[5,7]]]])
然后回到目标形状。这最后一步创建了原始副本(前面的步骤是 view
):
In [19]: x.reshape(2,3).reshape(4,8)
Out[19]:
array([[0,[4,7]])
很难概括这一点,因为有不同的重新排列块的方法。例如我的第一次尝试产生:
In [16]: x.reshape(4,4).transpose(1,2).reshape(4,8)
Out[16]:
array([[0,7]])