性能和内存使用方面的注意事项
Timestamp和Period都是以64位整数表示的(即NumPy的datetime64数据类型)。也就是说,对于每个数据点,其时间戳需要占用8字节的内存。因此,含有一百万个float64数据点的时间序列需要占用大约16MB的内存空间。由于pandas会尽量在多个时间序列之间共享索引,所以创建现有时间序列的视图不会占用更多内存译注11。此外,低频率索引(日以上)会被存放在一个中心缓存中,所以任何固定频率的索引都是该日期缓存的视图。所以,如果你有一个很大的低频率时间序列,索引所占用的内存空间将不会很大。
性能方面,pandas对数据对齐(两个不同索引的ts1+ts2的幕后工作)和重采样运算进行了高度优化。下面这个例子将一亿个数据点聚合为OHLC:
- In [582]: rng = pd.date_range('1/1/2000', periods=10000000, freq='10ms')
- In [583]: ts = Series(np.random.randn(len(rng)), index=rng)
- In [584]: ts
- Out[584]:
- 2000-01-01 00:00:00 -1.402235
- 2000-01-01 00:00:00.010000 2.424667
- 2000-01-01 00:00:00.020000 -1.956042
- 2000-01-01 00:00:00.030000 -0.897339
- ...
- 2000-01-02 03:46:39.960000 0.495530
- 2000-01-02 03:46:39.970000 0.574766
- 2000-01-02 03:46:39.980000 1.348374
- 2000-01-02 03:46:39.990000 0.665034
- Freq: 10L, Length: 10000000
- In [585]: ts.resample('15min', how='ohlc')
- Out[585]:
- <class 'pandas.core.frame.DataFrame'>
- DatetimeIndex: 113 entries, 2000-01-01 00:00:00 to 2000-01-02 04:00:00
- Freq: 15T
- Data columns:
- open 113 non-null values
- high 113 non-null values
- low 113 non-null values
- close 113 non-null values
- dtypes: float64(4)
- In [586]: %timeit ts.resample('15min', how='ohlc')
- 10 loops, best of 3: 61.1 ms per loop
运行时间跟聚合结果的相对大小有一定关系,越高频率的聚合所耗费的时间越多:
- In [587]: rng = pd.date_range('1/1/2000', periods=10000000, freq='1s')
- In [588]: ts = Series(np.random.randn(len(rng)), index=rng)
- In [589]: %timeit ts.resample('15s', how='ohlc')
- 1 loops, best of 3: 88.2 ms per loop
可能在你阅读本书的时候,这些算法的性能已经大为改进了。比如说,目前并没有对规则频率之间的转换做任何优化,但这肯定是要做的。
译注11:原文就是这么表达的。我感到很不解,既然是视图,当然不会占用多少内容,毕竟就是比单个指针大点的东西而已。结合上下文来看,估计说的只是索引的问题。