将 numpy.fromiter 与自定义函数一起使用

Using numpy.fromiter with custom function

我想使用 numpy.fromiter

构建一个 numpy.array(形状 (3, 2)

numpy 数组将由 3 个 numpy 数组组成,每个数组包含 2 个浮点数。这 3 个数组将是自定义函数的输出,但对于示例,我将使用 numpy.random.randn.

受到 documentation 的启发,我的代码如下所示:

iterable = (np.random.randn(2) for _ in range(3))
np.fromiter(iterable, float, 3)

但是我收到以下我不理解的错误:

ValueError: setting an array element with a sequence.

我可以简单地使用 np.array([np.random.randn(2) for _ in range(3)])(按我的意愿工作),但据我所知,它的效率会降低,因为列表是实际构建的

您的 iterable 生成一个大小为 2 的数组序列:

In [273]: for i in iterable:print(i)                                            
[0.72823755 2.04461013]
[-0.17102804  0.14188038]
[-1.1838654   1.01953532]

但是 fromiter 需要一系列浮点数 - 一次 1 个浮点数。

Create a new 1-dimensional array from an iterable object.

但是你的列表版本生成了一个二维数组!

===

定义结构化数组数据类型:

In [283]: dt=np.dtype('f,f')                                                    
In [284]: dt                                                                    
Out[284]: dtype([('f0', '<f4'), ('f1', '<f4')])

In [285]: iterable = (np.random.randn(2) for _ in range(3))                     
In [286]: np.fromiter(iterable,dt, 3)                                           
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-286-0301507c38c2> in <module>
----> 1 np.fromiter(iterable,dt, 3)

ValueError: setting an array element with a sequence.

使迭代器产生一个元组序列(结构化数组的正常输入是一个元组列表):

In [287]: iterable = (tuple(np.random.randn(2)) for _ in range(3))              
In [288]: np.fromiter(iterable,dt, 3)                                           
Out[288]: 
array([(-0.56128544,  0.03609687), ( 0.4170706 , -1.5592302 ),
       ( 2.4143908 , -0.96777505)], dtype=[('f0', '<f4'), ('f1', '<f4')])

docs 明确声明

Create a new 1-dimensional array from an iterable object.

这与您显式传入 dtype 的事实一致。在你的例子中,ndarray 不是 float,因此是错误。

你可以通过展平输入迭代来解决这个问题,例如 itertools.chain.from_iterable:

np.fromiter(itertools.chain.from_iterable(iterable), float, 6).reshape(3, 2)

这种方法的优点是它不会构建任何中间数据结构,即使是对于单独的行也是如此。一种稍微昂贵但可能不那么神秘的方法是直接将 iterable 扩展为 itertools.chain

 np.fromiter(itertools.chain(*iterable), float, 6).reshape(3, 2)