【发布时间】:2017-09-18 01:55:57
【问题描述】:
根据here 的答案,似乎没有一种简单的方法可以用生成器中的数据填充二维 numpy 数组。
但是,如果有人能想到一种方法来矢量化或以其他方式加速以下功能,我将不胜感激。
这里的区别是我想批量处理来自生成器的值,而不是在内存中创建整个数组。我能想到的唯一方法是使用 for 循环。
import numpy as np
from itertools import permutations
permutations_of_values = permutations(range(1,20), 7)
def array_from_generator(generator, arr):
"""Fills the numpy array provided with values from
the generator provided. Number of columns in arr
must match the number of values yielded by the
generator."""
count = 0
for row in arr:
try:
item = next(generator)
except StopIteration:
break
row[:] = item
count += 1
return arr[:count,:]
batch_size = 100000
empty_array = np.empty((batch_size, 7), dtype=int)
batch_of_values = array_from_generator(permutations_of_values, empty_array)
print(batch_of_values[0:5])
输出:
[[ 1 2 3 4 5 6 7]
[ 1 2 3 4 5 6 8]
[ 1 2 3 4 5 6 9]
[ 1 2 3 4 5 6 10]
[ 1 2 3 4 5 6 11]]
速度测试:
%timeit array_from_generator(permutations_of_values, empty_array)
10 loops, best of 3: 137 ms per loop
补充:
正如@COLDSPEED 所建议的(谢谢),这里是一个使用列表从生成器收集数据的版本。它大约是上面代码的两倍。任何人都可以对此进行改进:
permutations_of_values = permutations(range(1,20), 7)
def array_from_generator2(generator, rows=batch_size):
"""Creates a numpy array from a specified number
of values from the generator provided."""
data = []
for row in range(rows):
try:
data.append(next(generator))
except StopIteration:
break
return np.array(data)
batch_size = 100000
batch_of_values = array_from_generator2(permutations_of_values, rows=100000)
print(batch_of_values[0:5])
输出:
[[ 1 2 3 4 5 6 7]
[ 1 2 3 4 5 6 8]
[ 1 2 3 4 5 6 9]
[ 1 2 3 4 5 6 10]
[ 1 2 3 4 5 6 11]]
速度测试:
%timeit array_from_generator2(permutations_of_values, rows=100000)
10 loops, best of 3: 85.6 ms per loop
【问题讨论】:
-
填写一个列表然后在结果上调用
np.array应该更简单。 -
fromiter,正如在几个链接的答案中所讨论的,是直接从生成器的输出创建数组的唯一方法。否则,您需要创建一个列表并从中构建或填充数组。生成器可以在中间处理期间节省内存(参见等效的列表),但速度不会更快。 -
fromiter会很棒,但它只适用于系列(一维数组)。 -
你能提前知道尺寸吗?那么你仍然可以使用
fromiter -
如果您阅读文档,它指出
fromiter创建“从可迭代对象创建新的一维数组”。我在这里尝试做的是二维的,因为生成器中的每个项目都是 7 个值的元组。也许是时候扩展fromiter来处理多维迭代器了……
标签: python arrays numpy multidimensional-array itertools