2. 智能切分时间序列
# 从hdf5文件crime.h5读取丹佛市的crimes数据集,输出列数据的数据类型和数据的前几行
In[44]: crime = pd.read_hdf('data/crime.h5', 'crime')
crime.dtypes
Out[44]: OFFENSE_TYPE_ID category
OFFENSE_CATEGORY_ID category
REPORTED_DATE datetime64[ns]
GEO_LON float64
GEO_LAT float64
NEIGHBORHOOD_ID category
IS_CRIME int64
IS_TRAFFIC int64
dtype: object
In[45]: crime = crime.set_index('REPORTED_DATE')
crime.head()
Out[45]:
# 注意到有三个类型列和一个Timestamp对象列,这些数据的数据类型在创建时就建立了对应的数据类型。
# 这和csv文件非常不同,csv文件保存的只是字符串。
# 由于前面已经将REPORTED_DATE设为了行索引,所以就可以进行智能Timestamp对象切分。
In[46]: pd.options.display.max_rows = 4
In[47]: crime.loc['2016-05-12 16:45:00']
Out[47]:
# 可以进行时间部分匹配
In[48]: crime.loc['2016-05-12']
Out[48]:
# 也可以选取一整月、一整年或某天的某小时
In[49]: crime.loc['2016-05'].shape
Out[49]: (8012, 7)
In[50]: crime.loc['2016'].shape
Out[50]: (91076, 7)
In[51]: crime.loc['2016-05-12 03'].shape
Out[51]: (4, 7)
# 也可以包含月的名字
In[52]: crime.loc['Dec 2015'].sort_index()
Out[52]:
# 其它一些字符串的格式也可行
In[53]: crime.loc['2016 Sep, 15'].shape
Out[53]: (252, 7)
In[54]: crime.loc['21st October 2014 05'].shape
Out[54]: (4, 7)
# 可以进行切片
In[55]: crime.loc['2015-3-4':'2016-1-1'].sort_index()
Out[55]:
# 提供更为精确的时间
In[56]: crime.loc['2015-3-4 22':'2016-1-1 23:45:00'].sort_index()
Out[56]:
原理
# hdf5文件可以保存每一列的数据类型,可以极大减少内存的使用。
# 在上面的例子中,三个列被存成了类型,而不是对象。存成对象的话,消耗的内存会变为之前的四倍。
In[57]: mem_cat = crime.memory_usage().sum()
mem_obj = crime.astype({'OFFENSE_TYPE_ID':'object',
'OFFENSE_CATEGORY_ID':'object',
'NEIGHBORHOOD_ID':'object'}).memory_usage(deep=True)\
.sum()
mb = 2 ** 20
round(mem_cat / mb, 1), round(mem_obj / mb, 1)
Out[57]: (29.4, 122.7)
# 为了用日期智能选取和切分,行索引必须包含日期。
# 在前面的例子中,REPORTED_DATE被设成了行索引,行索引从而成了DatetimeIndex对象。
In[58]: crime.index[:2]
Out[58]: DatetimeIndex(['2014-06-29 02:01:00', '2014-06-29 01:54:00'], dtype='datetime64[ns]', name='REPORTED_DATE', freq=None)
更多
# 对行索引进行排序,可以极大地提高速度
In[59]: %timeit crime.loc['2015-3-4':'2016-1-1']
42.4 ms ± 865 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In[60]: crime_sort = crime.sort_index()
In[61]: %timeit crime_sort.loc['2015-3-4':'2016-1-1']
840 µs ± 32.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In[62]: pd.options.display.max_rows = 60