np.recarray 分配非常慢

问题描述

我用 ndarray 存储分时,每个分时都有一个 utc_timestamp[str] 作为索引,分时价格/vols 作为值。因此,我有一个包含 2 个不同 dtype(str 和 float)的数组。这是我将它存储为 np.recarray 的方式

data = np.recarray((100,),dtype=[('time':'U23'),('ask1':'f'),('bid1':'f')])
tick = ['2021-04-28T09:38:30.928',14.21,14.2]

# assigning this tick to the end of data,wield
%%timeit
  ...: data[-1] = np.rec.array(tick)
  ...: 
1.38 ms ± 13.9 µs per loop (mean ± std. dev. of 7 runs,1000 loops each)

每个循环花费 1.38 毫秒!!另外,我无法使用 data[-1] = tick 设置最后一行,这会引发 ValueError:使用序列设置数组元素

让我们尝试简单的 ndarray,假设我有 2 个单独的数组,一个用于 str,另一个用于 float

%%timeit
  ...: data[:,-1]=tick[1:]
  ...: 
15.2 µs ± 113 ns per loop (mean ± std. dev. of 7 runs,100000 loops each)

看到了吗?快了 90 倍!这是为什么?

解决方法

我的时间好多了:

In [503]: timeit data[-1] = np.rec.array(tick)
64.4 µs ± 321 ns per loop (mean ± std. dev. of 7 runs,10000 loops each)

np.rec.array(tick) 创建一个 dtype=[('f0','<U23'),('f1','<f8'),('f2','<f8')])。如果我使用最终的 dtype,我的速度会更快。

In [504]: timeit data[-1] = np.rec.array(tick,data.dtype)
31.1 µs ± 22.9 ns per loop (mean ± std. dev. of 7 runs,10000 loops each)

大部分时间都在创建 1 term recarray:

In [516]: %timeit x = np.rec.array(tick,data.dtype)
29.9 µs ± 41.2 ns per loop (mean ± std. dev. of 7 runs,10000 loops each)

改为创建结构化数组:

In [517]: %timeit x = np.array(tuple(tick),data.dtype)    
2.71 µs ± 15.9 ns per loop (mean ± std. dev. of 7 runs,100000 loops each)

In [519]: timeit data[-1] = np.array(tuple(tick),data.dtype)
3.58 µs ± 11.8 ns per loop (mean ± std. dev. of 7 runs,100000 loops each)

所以完全跳过recarray

In [521]: data = np.zeros((100,),dtype=[('time','U23'),('ask1','f'),('bid1','f')])
     ...: tick = ('2021-04-28T09:38:30.928',14.21,14.2)
In [522]: data[-1] = np.array(tick,data.dtype)
In [523]: data[-2:]
Out[523]: 
array([('',0.,0. ),('2021-04-28T09:38:30.928',14.2)],'<f4'),'<f4')])

我认为 recarray 在很大程度上已被结构化数组所取代。 recarray 添加的主要功能是将字段作为属性进行寻址的能力

data.time,data.ask1
data['time'],data['ask1']

您的示例表明 recarray 会减慢速度。

编辑

元组刻度可以直接赋值,无需额外转换:

In [526]: timeit data[-1] = tick
365 ns ± 0.247 ns per loop (mean ± std. dev. of 7 runs,1000000 loops each)