使用numpy array_split()获得所需的拆分大小,而不是约数

时间:2019-02-16 14:23:25

标签: python numpy numpy-ndarray

我有一个字节数组,大小为268238。(dtype =“ uint8”) 我如何将它们分成大小分别为2211的子数组? 其余数组可以更小。

通常:出于某种原因,我尝试使用numpy将文件拆分为大小为2211字节的块。 (其他信息:之后,我想对数组中的所有2211个元素进行base64_encode,但这仅用于您的其他信息)

# create an array to test the problem
import numpy as np
a = np.random.randint(255, size=268238).astype("uint8")
# check size and dtype.
a.size
a.dtype
# until now everything is fine
# now i want to split it in equal parts of 2211 elements
# last one may be smaller
# 
https://docs.scipy.org/doc/numpy/reference/generated/numpy.array_split.html
# just take the elements size now... 
(np.array_split(a, a.size // 2211))[0].size # <-- 2217... but why?
(np.array_split(a, a.size // 2211))[1].size # <-- 2217... but why?
# ...
(np.array_split(a, a.size // 2211))[120].size # <-- 2216 (remainder..)

numpy.array_split方法是否存在错误?

我期望每个块都是2211个元素(uint8的2211个数字)。相反,我得到的块大小为2217个元素。 我使用119、120、121还是122作为array_split的参数都没关系。我仍然没有获得2211的块大小。

在此先感谢您的帮助:)

**编辑:** 这项工作已经完成,但问题需要解答, 为什么array_split的行为异常。有人可以解释吗?

out = [a[i : i + 2211] for i in range(0, len(a), 2211)]
out[121].size
#  707 <-- the correct remainder

1 个答案:

答案 0 :(得分:1)

array_split()上的numpy documentation表示,除了将每个片段的大小传递给array_split()函数外,您还可以选择将索引传递到要进行拆分的位置。 使用此想法,以下代码将为您提供所需的结果:

import numpy as np
a = np.random.randint(255, size=268238).astype("uint8")
split_positions = list(range(2211,268238,2211))
split_result = np.array_split(a, split_positions)
frag_size_list = [p.size for p in split_result]
print (frag_size_list)

此输出为:

[2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 707]

您的代码无法正常工作的原因与所涉及的算法有关。如果您尝试使用片段大小重新计算原始大小,您将意识到这一点。

进一步详细说明代码为何无效:

268238 /  2211 = 121.3198
268238 // 2211 = 121

您正在将121作为片段数传递给array_split()函数。但这会产生您想要的2211的碎片大小吗?下面的算法说不会:

268238 / 121 = 2216.843(大约为2217)。