[英]Efficient conversion of a 3D numpy array to a 1D numpy array
I have a 3D numpy array in this form: 我有这种形式的3D numpy数组:
>>>img.shape
(4504932, 2, 2)
>>> img
array([[[15114, 15306],
[15305, 15304]],
[[15305, 15306],
[15303, 15304]],
[[15305, 15306],
[15303, 15304]],
...,
[[15305, 15302],
[15305, 15302]]], dtype=uint16)
Which I want to convert to a 1D numpy array where each entry is the sum of each 2x2 submatrix in the above img numpy array. 我想将其转换为一个1D numpy数组,其中每个条目都是上述img numpy数组中每个2x2子矩阵的总和。
I have been able to accomplish this using: 我已经能够使用以下方法完成此任务:
img_new = np.array([i.sum() for i in img])
>>> img_new
array([61029, 61218, 61218, ..., 61214, 61214, 61214], dtype=uint64)
Which is exactly what I want. 这正是我想要的。 But this is too slow (takes about 10 seconds).
但这太慢了(大约需要10秒)。 Is there a faster method I could use?
有没有我可以使用的更快的方法? I included above
img.shape
so you had an idea of the size of this numpy array. 我在
img.shape
上面包含了它,因此您对这个numpy数组的大小有所了解。
EDIT - ADDITIONAL INFO: My img
array could also be a 3D array in the form of 4x4, 5x5, 7x7.. etc submatrices. 编辑-其他信息:我的
img
数组也可以是4x4、5x5、7x7等子矩阵形式的3D数组。 This is specified by the variables sub_rows
and sub_cols
. 这由变量
sub_rows
和sub_cols
指定。
img.sum(axis=(1, 2))
sum
allows you to specify an axis or axes along which to sum, rather than just summing the whole array. sum
允许您指定一个或多个沿轴求和,而不仅仅是对整个数组求和。 This allows NumPy to loop over the array in C and perform just a few machine instructions per sum, rather than having to go through the Python bytecode evaluation loop and create a ton of wrapper objects to stick in a list. 这使NumPy可以在C语言中循环遍历数组,并且每个和仅执行几条机器指令,而不必经过Python字节码评估循环并创建大量包装对象以粘贴在列表中。
Using a numpy method ( apply_over_axes
) is usually quicker and indeed that is the case here. 通常,使用numpy方法(
apply_over_axes
)更快,实际上就是这种情况。 I just tested on a 4000x2x2 array: 我刚刚在4000x2x2阵列上进行了测试:
img = np.random.rand(4000,2,2)
timeit(np.apply_along_axis(np.sum, img, [1,2]))
# 1000 loops, best of 3: 721 us per loop
timeit(np.array([i.sum() for i in img]))
# 100 loops, best of 3: 17.2 ms per loop
You can use np.einsum
- 您可以使用
np.einsum
img_new = np.einsum('ijk->i',img)
Verify results 验证结果
In [42]: np.array_equal(np.array([i.sum() for i in img]),np.einsum('ijk->i',img))
Out[42]: True
Runtime tests 运行时测试
In [34]: img = np.random.randint(0,10000,(10000,2,2)).astype('uint16')
In [35]: %timeit np.array([i.sum() for i in img]) # Original approach
10 loops, best of 3: 92.4 ms per loop
In [36]: %timeit img.sum(axis=(1, 2)) # From other solution
1000 loops, best of 3: 297 µs per loop
In [37]: %timeit np.einsum('ijk->i',img)
10000 loops, best of 3: 102 µs per loop
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.