简体   繁体   English

如何在没有 for 循环的情况下使用 numpy 块修改 3d 阵列?

[英]How to modify a 3d array using numpy block without for loop?

I want to modify block elements of 3d array without for loop.我想在没有 for 循环的情况下修改 3d 数组的块元素。 Without loop because it is the bottleneck of my code.没有循环,因为它是我的代码的瓶颈。

To illustrate what I want, I draw a figure:为了说明我想要什么,我画了一个图:

在此处输入图像描述

The code with for loop:带有for循环的代码:

import numpy as np

# Create 3d array with 2x4x4 elements
a = np.arange(2*4*4).reshape(2,4,4)
b = np.zeros(np.shape(a))

# Change Block Elements

for it1 in range(2):
    b[it1]= np.block([[a[it1,0:2,0:2], a[it1,2:4,0:2]],[a[it1,0:2,2:4], a[it1,2:4,2:4]]] )

You can directly replace the it1 by a slice of the whole dimension:您可以直接将it1替换为整个维度的切片:

b = np.block([[a[:,0:2,0:2], a[:,2:4,0:2]],[a[:,0:2,2:4], a[:,2:4,2:4]]])

First let's see if there's a way to do what you want for a 2D array using only indexing, reshape , and transpose operations.首先让我们看看是否有一种方法可以只使用索引、 reshapetranspose操作来为 2D 数组做你想做的事情。 If there is, then there's a good chance that you can extend it to a larger number of dimensions.如果有,那么您很有可能可以将其扩展到更多维度。

x = np.arange(2 * 3 * 2 * 5).reshape(2 * 3, 2 * 5)

Clearly you can reshape this into an array that has the blocks along a separate dimension:显然,您可以将其重塑为具有沿单独维度的块的数组:

x.reshape(2, 3, 2, 5)

Then you can transpose the resulting blocks:然后您可以转置生成的块:

x.reshape(2, 3, 2, 5).transpose(2, 1, 0, 3)

So far, none of the data has been copied.到目前为止,没有任何数据被复制。 To make the copy happen, reshape back into the original shape:要进行复制,请重新整形为原始形状:

x.reshape(2, 3, 2, 5).transpose(2, 1, 0, 3).reshape(2 * 3, 2 * 5)

Adding additional leading dimensions is as simple as increasing the number of the dimensions you want to swap:添加其他前导维度就像增加要交换的维度数量一样简单:

b = a.reshape(a.shape[0], 2, a.shape[1] // 2, 2, a.shape[2] // 2).transpose(0, 3, 2, 1, 4).reshape(a.shape)

Here is a quick benchmark of the other implementations with your original array:这是使用原始数组的其他实现的快速基准:

a = np.arange(2*4*4).reshape(2,4,4)

%%timeit
b = np.zeros(np.shape(a))
for it1 in range(2):
    b[it1] = np.block([[a[it1, 0:2, 0:2], a[it1, 2:4, 0:2]], [a[it1, 0:2, 2:4], a[it1, 2:4, 2:4]]])
    
27.7 µs ± 107 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%%timeit
b = a.copy()
b[:,0:2,2:4], b[:,2:4,0:2] = b[:,2:4,0:2].copy(), b[:,0:2,2:4].copy()

2.22 µs ± 3.89 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit b = np.block([[a[:,0:2,0:2], a[:,2:4,0:2]],[a[:,0:2,2:4], a[:,2:4,2:4]]])

13.6 µs ± 217 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit b = a.reshape(a.shape[0], 2, a.shape[1] // 2, 2, a.shape[2] // 2).transpose(0, 3, 2, 1, 4).reshape(a.shape)

1.27 µs ± 14.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

For small arrays, the differences can sometimes be attributed to overhead.对于小型 arrays,差异有时可归因于开销。 Here is a more meaningful comparison with arrays of size 10x1000x1000, split into 10 500x500 blocks:这是与大小为 10x1000x1000 的 arrays 的更有意义的比较,分为 10 个 500x500 块:

a = np.arange(10*1000*1000).reshape(10, 1000, 1000)

%%timeit
b = np.zeros(np.shape(a))
for it1 in range(10):
    b[it1]= np.block([[a[it1,0:500,0:500], a[it1,500:1000,0:500]],[a[it1,0:500,500:1000], a[it1,500:1000,500:1000]]])

58 ms ± 904 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
b = a.copy()
b[:,0:500,500:1000], b[:,500:1000,0:500] = b[:,500:1000,0:500].copy(), b[:,0:500,500:1000].copy()

41.2 ms ± 688 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit b = np.block([[a[:,0:500,0:500], a[:,500:1000,0:500]],[a[:,0:500,500:1000], a[:,500:1000,500:1000]]])

27.5 ms ± 569 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit b = a.reshape(a.shape[0], 2, a.shape[1] // 2, 2, a.shape[2] // 2).transpose(0, 3, 2, 1, 4).reshape(a.shape)

20 ms ± 161 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

So it seems that using numpy's own reshaping and transposition mechanism is fastest on my computer.所以看来在我的电脑上使用numpy自己的reshaping和transposition机制是最快的。 Also, notice that the overhead of np.block becomes less important than copying the temporary arrays as size gets bigger, so the other two implementations change places.另外,请注意,随着大小变大, np.block的开销变得不如复制临时 arrays 重要,因此其他两个实现改变了位置。

Will it make it faster?它会让它更快吗?

import numpy as np
a = np.arange(2*4*4).reshape(2,4,4)
b = a.copy()
b[:,0:2,2:4], b[:,2:4,0:2] = b[:,2:4,0:2].copy(), b[:,0:2,2:4].copy()


Comparison with np.block() alternative from another answer.与另一个答案的 np.block() 替代方案进行比较。

Option 1 :选项 1

%timeit b = a.copy(); b[:,0:2,2:4], b[:,2:4,0:2] = b[:,2:4,0:2].copy(), b[:,0:2,2:4].copy()

Output: Output:

5.44 µs ± 134 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)


Option 2选项 2

%timeit b = np.block([[a[:,0:2,0:2], a[:,2:4,0:2]],[a[:,0:2,2:4], a[:,2:4,2:4]]])

Output: Output:

30.6 µs ± 1.75 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在没有循环的情况下在特定位置修改2D numpy数组? - how to modify a 2D numpy array at specific locations without a loop? 如何有效地修改具有数百万个单元的Numpy 3D数组 - How to efficiently modify a numpy 3D array with millions of cells 平行修改切片中的3D numpy数组 - Modify 3D numpy array in slices in parallel 在没有for循环的情况下,在特定位置修改Numpy 2D数组的元素 - Modify the elements of a Numpy 2D- array at specific locations without for loop 如何在不使用 for 循环的情况下填充二维二进制 Numpy 数组? - How to fill 2D binary Numpy array without using for loop? 如何在循环中使用numpy从python中的2D数组高效创建3D数组? - How to efficiently create a 3D array from 2D arrays in python using numpy in a loop? 3D numpy数组成块对角矩阵 - 3D numpy array into block diagonal matrix 如何在不使用循环的情况下为3D numpy数组中的每个值进行N个随机选择 - How to make N random choices for each value in a 3D numpy array without using loops 如何在不使用 python 循环的情况下将元素插入 3d numpy 数组中的特定索引? - How to insert element to a specific index in 3d numpy array without using python loops? numpy 将 2D 矩阵重塑为无循环对称矩阵(3D 数组)数组 - numpy reshaping a 2D matrix into an array of symmetric matrix (3D array) without loop
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM