3.6 相互转换
时间戳与时期之间的转换
时间戳转时间段
# 时间戳与时期之间的转换:pd.to_period()、pd.to_timestamp() # 每月最后一日,转化为每月 rng = pd.date_range('2020/1/1', periods = 3, freq = 'M') ts1 = pd.Series(np.arange(len(rng)), index = rng) print(ts1.head()) print(ts1.to_period().head()) print(type(ts1.index),type(ts1.to_period().index)) # <class 'pandas.core.indexes.datetimes.DatetimeIndex'> <class 'pandas.core.indexes.period.PeriodIndex'>
输出为:
2020-01-31 0 2020-02-29 1 2020-03-31 2 Freq: M, dtype: int32 2020-01 0 2020-02 1 2020-03 2 Freq: M, dtype: int32 <class 'pandas.core.indexes.datetimes.DatetimeIndex'> <class 'pandas.core.indexes.period.PeriodIndex'> print('*'*10)
时间段转时间戳
# 每月,转化为每月第一天 prng = pd.period_range('2020','2021', freq = 'M') ts2 = pd.Series(np.arange(len(prng)), index = prng) print(ts2.head()) print(ts2.to_timestamp().head()) print(type(ts2.index),type(ts2.to_timestamp().index))
3.7 日期偏置DateOffset的构造与属性
概念 | 单元素类型 | 数组类型 | pandas数据类型 |
Date times | Timestamp |
DatetimeIndex |
datetime64[ns] |
Time deltas | Timedelta |
TimedeltaIndex |
timedelta64[ns] |
Time spans | Period |
PeriodIndex |
period[freq] |
Date offsets | DateOffset |
None |
None |
Offset对象
日期偏置是一种和日历相关的特殊时间差,例如回到第一节中的两个问题:如何求2020年9月第一个周一的日期,以及如何求2020年9月7日后的第30个工作日是哪一天。
求下一个月的第几周的周几,week=0表示为第1周,weekday=0表示为周日
# week=0表示为第1周,weekday=0表示为周日 pd.Timestamp('20220905') + pd.offsets.WeekOfMonth(week=0,weekday=0)
输出为:
Timestamp('2022-10-03 00:00:00')
偏移30天
pd.Timestamp('20220907') + pd.offsets.BDay(30)
输出为:
Timestamp('2022-10-19 00:00:00')
常用的日期偏置如下可以查阅这里的文档描述。在文档罗列的Offset中,需要介绍一个特殊的Offset对象CDay,其中的holidays, weekmask参数能够分别对自定义的日期和星期进行过滤,前者传入了需要过滤的日期列表,后者传入的是三个字母的星期缩写构成的星期字符串,其作用是只保留字符串中出现的星期。
3.8 时序中的滑窗与分组
1. 滑动窗口
所谓时序的滑窗函数,即把滑动窗口用freq关键词代替,下面给出一个具体的应用案例:在股票市场中有一个指标为BOLL指标,它由中轨线、上轨线、下轨线这三根线构成,具体的计算方法分别是N日均值线、N日均值加两倍N日标准差线、N日均值减两倍N日标准差线。利用rolling对象计算N=30的BOLL指标可以如下写出:
import matplotlib.pyplot as plt idx = pd.date_range('20200101', '20201231', freq='B') np.random.seed(2020) data = np.random.randint(-1,2,len(idx)).cumsum() # 随机游动构造模拟序列 s = pd.Series(data,index=idx) s
输出为:
2020-01-01 -1 2020-01-02 -2 2020-01-03 -1 2020-01-06 -1 2020-01-07 -2 .. 2020-12-25 17 2020-12-28 18 2020-12-29 19 2020-12-30 19 2020-12-31 18 Freq: B, Length: 262, dtype: int32
r = s.rolling('30D') r
输出为:
Rolling [window=2592000000000000,min_periods=1,center=False,win_type=freq,axis=0]
可视化:
plt.plot(s,label='30D') plt.title('BOLL LINES') plt.plot(r.mean(),label='mean') plt.plot(r.mean()+r.std()*2,label='mean+std()*2') plt.plot(r.mean()-r.std()*2,label='mean-std()*2') plt.legend() plt.show()
输出为:
对于shift函数而言,作用在datetime64为索引的序列上时,可以指定freq单位进行滑动:
s.shift(freq='1D')
输出为:
2.重采样
重采样对象resample和分组对象groupby的用法类似,前者是针对时间序列的分组计算而设计的分组对象。
例如,对上面的序列计算每个月的均值:
s.resample('1M').mean()
输出为:
2020-01-31 -3.000000 2020-02-29 -0.750000 2020-03-31 3.090909 2020-04-30 6.818182 2020-05-31 5.952381 2020-06-30 8.954545 2020-07-31 11.217391 2020-08-31 7.952381 2020-09-30 10.727273 2020-10-31 8.863636 2020-11-30 14.952381 2020-12-31 19.695652 Freq: M, dtype: float64
s1 = s.copy() s1.index = s_month s1
输出为:
1 -1 1 -2 1 -1 1 -1 1 -2 .. 12 17 12 18 12 19 12 19 12 18 Length: 262, dtype: int32
采用分组的办法求均值
s1.reset_index().groupby(by='index').mean()
输出为:
同时,如果没有内置定义的处理函数,可以通过apply方法自定义:
s.resample('1M').apply(lambda x:x.max()-x.min()) # 极差
输出为
2020-01-31 4 2020-02-29 7 2020-03-31 5 2020-04-30 3 2020-05-31 5 2020-06-30 7 2020-07-31 5 2020-08-31 2 2020-09-30 5 2020-10-31 4 2020-11-30 10 2020-12-31 4 Freq: M, dtype: int32
在resample中要特别注意组边界值的处理情况,默认情况下起始值的计算方法是从最小值时间戳对应日期的午夜00:00:00开始增加freq,直到不超过该最小时间戳的最大时间戳,由此对应的时间戳为起始值,然后每次累加freq参数作为分割结点进行分组,区间情况为左闭右开。