时间序列&日期学习笔记大全(下)

时间:2022-07-25
本文章向大家介绍时间序列&日期学习笔记大全(下),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

作者:湛林

来源:凹凸数据

时间序列&日期学习笔记大全(上)

建议收藏

9. 日期 时间的组成

dt.方法,具体参数及含义详见附件

# 可以通过s.dt.time 获得各种信息
s.dt.year
s.dt.date
# 可以用于筛选日期数据
s[s.dt.day == 2]
# 将日期数据转化为字符串数据,并设置格式
s.dt.strftime('%Y/%m/%d')

10. 日期偏移量

Dateoffset参数可以用于freq参数,详见附件

friday = pd.Timestamp('2018-01-05')
two_business_days = 2 * pd.offsets.BDay()
friday + two_business_days
two_business_days.apply(friday)
d = datetime.datetime(2008, 8, 18, 9, 0)
# pd.offsets.Week() 加一周的时间
d + pd.offsets.Week()
# 默认一周7天,可以穿参数 一周设置为4天
d + pd.offsets.Week(weekday=4)
# 加减天数后,把时间重置为午夜时分 normalize=True
d + pd.offsets.Week(normalize=True)
# 直接到年底的函数,默认是12月是最后一个月,可以传参数设置年底月份(用于财务年度)
 d + pd.offsets.YearEnd(month=6)

11. 对Series和数据框使用日期偏移

可以将偏移量应用到每个元素

rng = pd.date_range('2012-01-01', '2012-01-03')
s = pd.Series(rng)
# 对s 序列所有日期进行偏移,偏移2个月
s + pd.DateOffset(months=2)
# 偏移的是日,时分秒的时候,可以直接类似timedelta使用
s - pd.offsets.Day(2)
s - pd.Series(pd.date_range('2011-12-29', '2011-12-31'))
s + pd.offsets.Minute(15)

定制工作日方法详见 Custom business days

定制工作时间的方法 详见 Business hour和 Custom business hour、

对于一些固定的偏移量,可以参考Anchored offsets

12. 锚定点偏移

当给定的时间是锚定点(月底,月初等),那就往后或往前走n-1步。

给定的时间是锚定点(月初,月末),往后/前走n步

In [236]: pd.Timestamp('2014-01-02') + pd.offsets.MonthBegin(n=1)
Out[236]: Timestamp('2014-02-01 00:00:00')

In [237]: pd.Timestamp('2014-01-02') + pd.offsets.MonthEnd(n=1)
Out[237]: Timestamp('2014-01-31 00:00:00')

In [238]: pd.Timestamp('2014-01-02') - pd.offsets.MonthBegin(n=1)
Out[238]: Timestamp('2014-01-01 00:00:00')

In [239]: pd.Timestamp('2014-01-02') - pd.offsets.MonthEnd(n=1)
Out[239]: Timestamp('2013-12-31 00:00:00')

In [240]: pd.Timestamp('2014-01-02') + pd.offsets.MonthBegin(n=4)
Out[240]: Timestamp('2014-05-01 00:00:00')

In [241]: pd.Timestamp('2014-01-02') - pd.offsets.MonthBegin(n=4)
Out[241]: Timestamp('2013-10-01 00:00:00')

13. 时间序列相关方法

13.1 转换时间频率

dr = pd.date_range('1/1/2010', periods=3, freq=3 * pd.offsets.BDay())
ts = pd.Series(np.random.randn(3), index=dr)
ts.asfreq(pd.offsets.BDay())
# 改变频率后,补充空值的方法
ts.asfreq(pd.offsets.BDay(), method='ffill')

14. 重新采样 resample

resample是一个基于时间的groupby方法,可以方便的用于频率转换,重采样功能非常灵活,允许指定许多不同的参数来控制频率转换和重采样操作。通过调度可用的任何函数都可以作为返回对象的方法使用,包括sum, mean, std, sem, max, min,median,first, last, ohlc

# 原数据是按 秒 来设置的
rng = pd.date_range('1/1/2012', periods=100, freq='S')
ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
# 按照1分钟重新采样数据,并求和
ts.resample('1Min').sum()
# 按照1分钟重新采样数据,并求 高开低收
ts.resample('1Min').ohlc()
# 源数据是按秒来设置的,要重新以250毫秒进行采样
ts[:2].resample('250L').asfreq()
ts[:2].resample('250L').ffill(limit=2)

15. 重新采样resample的参数 agg

df = pd.DataFrame(np.random.randn(1000, 3), index=pd.date_range('1/1/2012',
freq='S', periods=1000),columns=['A', 'B', 'C'])
# 和groupby函数使用方法类似
r = df.resample('3T')
# group内求平均值
r.mean()
# 对指定列的group求平均值
r['A'].mean()
# 对特定的几列的group求平均值
r[['A', 'B']].mean()
# 对特定列的group求和,求平均值,求标准差
r['A'].agg([np.sum, np.mean, np.std])
# 对整个数据框按group求和,求均值
r.agg([np.sum, np.mean])
# 对不同列求不同的统计数据
r.agg({'A': 'sum', 'B': 'std'})
# 对不同列求不同的多个统计数据
r.agg({'A': ['sum', 'std'], 'B': ['mean', 'std']})
  • 如果索引不方便设置为DatetimeIndex,可以用on将日期列传入
# 按M(月份)来重新采样,传入日期列
df.resample('M', on='date').sum()
# MultiIndex里有日期,那就用level来传入日期
df.resample('M', level='d').sum()

16. resample的遍历

# name是分组依据,group是分数后的数据
for name, group in resampled:
    print("Group: ", name)
    print("-" * 27)
    print(group, end="nn")

17. Period 周期 时期

# 可以用period_range 直接生成
# 用freq参数传入时期的频率
pd.Period('2012-1-1', freq='D')
# 周期时间可以相加减
p = pd.Period('2012-01', freq='2M')
p + 2
# 也可以加一个timedelta或offset,但是时间单位必须一样
p = pd.Period('2014-07-01 09:00', freq='H')
p + pd.offsets.Hour(2)                  # 加两小时
p + datetime.timedelta(minutes=120)     # 120分钟,俩小时
p + pd.offsets.Minute(5)                # 时间跨度单位不一致,报错
# 周期之间相减,返回之间的差值
pd.Period('2012', freq='A-DEC') - pd.Period('2002', freq='A-DEC')

18. 周期序列 PeriodIndex

# 可以用pd.period_range创建,也可以直接创建
prng = pd.period_range('1/1/2011', '1/1/2012', freq='M')
pd.PeriodIndex(['2011-1', '2011-2', '2011-3'], freq='M')
pd.period_range(start='2014-01', freq='3M', periods=4)      
# 周期序列也可以支持加减操作
idx = pd.period_range('2014-07-01 09:00', periods=5, freq='H')
idx + pd.offsets.Hour(2)

18.1 周期类型数据的转换

pi = pd.period_range('2016-01-01', periods=3, freq='M')
# 转换为天 为单位的周期
pi.astype('period[D]')
# 转换为时间序列
pi.astype('datetime64[ns]')
# 转换成周期序列
dti = pd.date_range('2011-01-01', freq='M', periods=3)
dti.astype('period[M]')

18.2 索引 切片,部分字符串索引

dfp = pd.DataFrame(np.random.randn(600, 1),columns=['A'],index=pd.period_range('2013-01-01 9:00',periods=600,freq='T'))
# 切片筛选2013-01-01 十点的全部数据
dfp['2013-01-01 10H']

18.3 改变周期的频率

和时间不同的是,周期频率从年变为月,也是一个数据。一年周期==>一个月周期,因此要设置改了之后是取开头还是取结尾

p = pd.Period('2011', freq='A-DEC')
p.asfreq('M', how='start')

自定义设置时间年度,会计年度详见Frequency conversion and resampling with PeriodIndex

18.4 周期和时间戳的转换

rng = pd.date_range('1/1/2012', periods=5, freq='M')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ps = ts.to_period()
ps.to_timestamp()
# 转换为时间戳时候,可以添加参数选择周期开头还是结尾
ps.to_timestamp('D', how='s')
# 将时间转为季度末下一天的早上九点
prng = pd.period_range('1990Q1', '2000Q4', freq='Q-NOV')
ts = pd.Series(np.random.randn(len(prng)), prng)
ts.index = (prng.asfreq('M', 'e') + 1).asfreq('H', 's') + 9

19. 与时区相关的知识

详见Time zone handling