将时间序列转换为一个具有固定的频率的时间序列
只需要调用resample即可:
import datetime
import pandas as pd
import numpy as np
dates = [
datetime.datetime(2011, 1, 2),
datetime.datetime(2011, 1, 5),
datetime.datetime(2011, 1, 7),
datetime.datetime(2011, 1, 8),
datetime.datetime(2011, 1, 10),
datetime.datetime(2011, 1, 12),
]
ts = pd.Series(np.random.randn(6), index=dates)
dts = ts.resample("D")
# print(dts) # DatetimeIndexResampler [freq=<Day>, axis=0, closed=left, label=left, convention=start, base=0]
使用基本的频率
生成时间范围:
# 默认情况下 传入起止时间会生成按天计算的时间点
index = pd.date_range('4/1/2012', '6/1/2012')
# print(index
# 如果我们只传入开始或者是结束时间 就要传入一个表示一段时间的数字
idx1 = pd.date_range(start='4/1/2012', periods=20)
# print(idx1)
idx2 = pd.date_range(end='6/1/2012', periods=20)
# print(idx2)
开始时间和结束时间定义了时间索引的严格边界 : BM(business end of month)
这样就只会包含时间间隔内的(或者正好在边界上的点)
ret1 = pd.date_range('1/1/2000', '12/1/2000', freq="BM")
# print(ret1)
# date_range默认会保留起始和结束时间戳的时间信息
ret2 = pd.date_range('5/2/2012 12:56:31', periods=5)
# print(ret2)
# 这时候如果我们想要的是一组被规范到午夜的时间戳 normalize 可以实现
ret3 = pd.date_range('5/2/2012 12:56:31', periods=5, normalize=True)
# print(ret3)
频率和日期偏移量
显式创建对象,
hour = pd.tseries.offsets.Hour()
# print(hour)
four_hour = pd.tseries.offsets.Hour(4)
# print(four_hour)
# 大部分的偏移对象可以通过加法进行连接
res = pd.tseries.offsets.Hour(4) + pd.tseries.offsets.Minute(30)
# print(res)
# 一般来说我们并不需要显式创建这样的对象
dts1 = pd.date_range('1/1/2000', '1/3/2000 23:59', freq="4h")
# print(dts1)
dts2 = pd.date_range('1/1/2000', periods=10, freq="2h30min")
# print(dts2)
锚点偏移量
有的频率所描述的时间不是均匀分布的 例如说 “M” 是 日历月末 “BM” 是每月的最后一个工作日
WOM 日期
WOM (week of month) 是一种很使用的频率类, 使我们能够获得诸如"每月第三个周五" 之类的日期
以下这是标准的股票期权月度到期日
rng = pd.date_range('1/1/2012', '9/1/2012', freq="WOM-3FRI")
# print(rng)
# print(list(rng))
移动(超前和滞后) 数据
移动是指沿着时间轴将数据前移或者后移
series 和 df 都有一个 shift 方法 用于执行单纯的前移或者后移 保持索引不变
ts = pd.Series(np.random.randn(4), index=pd.date_range('1/1/2000', periods=4, freq="M"))
# print(ts)
# 向下平移
ts1 = ts.shift(2)
# print(ts1)
# 向上平移
ts2 = ts.shift(-2)
# print(ts2)
# shift 通常是用来计算一个或者多个时间序列的百分比变化
ret = ts/ts.shift(1) - 1
# print(ret)
"""
单纯的位移不会修改索引 所以部分数据会被丢弃
如果频率已经知道 可以经其传递给 shift 以便实现对时间的位移而不是对数据进行简单位移
(只是移动时间轴 不移动数据)
"""
# print(ts)
# print(ts.shift(2, freq="M"))
# print(ts.shift(3, freq="D"))
# print(ts.shift(1, freq="3D"))
# print(ts.shift(1, freq="90T"))
通过偏移量对日期进行位移
from pandas.tseries.offsets import Day, MonthEnd, QuarterBegin, QuarterEnd
now = datetime.datetime(2011, 11, 17)
t1 = now + 3 * Day()
# print(t1)
# 等价于 datetime 中的 timedelta
t2 = now + datetime.timedelta(days=3)
# print(t2)
# print(t1 == t2)
# 如果加的是锚点偏移量 第一次增量会将原来的日期向前滚动到符合频率的规则的下一个日期
dt1 = now + MonthEnd()
# print(dt1)
dt2 = now - QuarterEnd()
# print(dt2)
# 也可以这样用 使用 锚点偏移量的 rollforward 和 rollback 方法
offset = MonthEnd()
tt1 = offset.rollback(now)
# print(tt1)
tt2 = offset.rollforward(now)
# print(tt2)
# 结合 groupby 使用日期偏移量
ts = pd.Series(np.random.randn(20), index=pd.date_range("1/15/2000", periods=20, freq='4d'))
# print(ts)
# 前向推出所有的月末数据 然后再分组求平均
ret2 = ts.groupby(offset.rollforward).mean()
# print(ret2)
# 更简单的方法是使用 resample 然后再使用 mean
ret3 = ts.resample("M", how="mean")
print(ret3)