time series:时间序列
目录:
文章目录
- @[toc]
- 一 时间序列总览
- 二 日期和时间数据类型及工具
- 1 日期和时间数据类型
- 2 字符串和datetime的相互转换
- 三 时间序列基础
- 1 索引、选取、子集构造
- 2 带有重复索引的时间序列
- 四 日期的范围、频率及移动
- 1 生成日期范围
- 2 频率和日期偏移量
- 3 移动(超前和滞后)数据
- 五 时区处理
- 1 本地化和转换
- 2 操作时区意识型Timestamp对象
- 3 不同时区之间的运算
- 六 时期及其算术运算
- 1 时期的频率转换
- 2 按季度计算的时期频率
- 3 将Timestamp转换为Period(及其反向过程)
- 4 通过数组创建PeriodIndex
- 七 重采样及频率转换
- 1 降采样
- 2 升采样和插值
- 3 通过时期进行重采样
- 八 时间序列绘图
- 九 移动窗口函数
- 1 指数加权函数
- 2 二元移动函数
- 3 用户自定义的移动窗口函数
一 时间序列总览
- 不管在哪个领域(金融学、经济学、生态学、神经科学、物理学等),时间序列(time series)数据都是一种重要的结构化数据形式。在多个时间点观察或测量到的任何事物都可以形成一段时间序列。很多时间序列都是固定频率的,基本数据点都是根据某种规律出现的;时间序列也可以是不定期的额。时间序列数据的意义取决于具体的应用场景,主要有以下几种:
- ① 时间戳(timestamp):特定的时刻
- ② 固定时期(period):如2007年1月或2014年全年
- ③ 时间间隔(interval):由起始和结束时间戳表示。时期可以被看做间隔的特例。
- ④ 实验过程时间,每个时间点都是相对于特定起始时间的一个度量。
- 许多技术都可以用来处理实验型时间序列,其索引可能是一个整数或浮点数(表示从实验开始算起已经过去的时间)。最简单也最常见的时间序列都是用时间 戳进行索引的。
- pandas提供了一组标准的时间序列处理工具和数据算法。可以高效处理非常大的时间序列,轻松进行切片/切块、聚合、对定期、不定期的时间序列进行重采样等。这些工具大部分都对金融和经济数据尤为重要,也可以用来分析服务器日志数据。
二 日期和时间数据类型及工具
1 日期和时间数据类型
- python标准库包含用于日期(date)和时间(time)数据的数据类型,而且还有日历方面的功能。主要用到datetime、time以及calendar模块。datetime.datetime是用得最多的数据类型。
from datetime import datetime
now = datetiem.now()
now.year,now.month,now.day
- datetime以毫秒形式存储日期和时间,datetime.timedelta表示连个datetime对象之间的时间差
delta = datetime(2011,1,4) - datetime(2008,9,8,8,15)
- 可以给datetime对象加上或减去一个或多个timedelta,这样会产生一个新对象。
- datetime时间模块数据类型:
- date #以公历形式存储的日历日期
- time # 将时间存储为时、分、秒、毫秒
- datetime # 存储日期和时间
- timedelta # 表示两个datetime值之间的差
2 字符串和datetime的相互转换
- 利用str或strtfime方法(传入一个格式化字符串),datetime对象和pandas的Timestamp对象可以被格式化为字符串。
stamp = datetime(2011,1,3)
stamp.strftime('%y-%m-%d')
- datetime格式定义:
- %Y 4位数的年
- %y 2位数的年
- %m 2位数的月
- %d 2位数的日
- %H 24小时制的时
- %I 12小时制的时
- %M 2位数的分
- %S 秒
- %w 用整数表示的星期几[0(星期天),6]
- %U 每年的第几周(00,53)。星期天被认为是每周的第一天,每年第一个星期天之前得那几天被认为是第“0周”
- %W 每年的第几周(00,53)。星期一被认为是每周的第一天,每年第一个星期一之前得那几天被认为是第“0周”
- %z 时区偏移量
- %F %Y-%m-%d简写形式,例如2012-4-18
- %D %m-%d-%y简写形式,例如04/18/12
- strptime也可以用这些格式化编码将字符串转换为日期。datetime.strptime是通过已知格式进行日期解析的最佳方式。但是每次都要编写格式定义是很麻烦的事情,尤其是对于一些常见的日期格式。这种情况下,可以用dateutil这个第三方包中的parser.parse方法,dateutil可以解析几乎所有人类能够理解的日期表示形式。
- 在国际通用的格式中,日通常出现在月的前面,传入dayfirst = True即可
- pandas通常用来处理成组日期,还可以处理缺失值。
- datetime对象还有一些特定于当前环境的格式化选项。
三 时间序列基础
- pandas最基本的时间序列类型就是以时间戳(通常以python字符串或datetime对象表示)为索引的Series。这些datetime对象实际上被放在一个datetimieIndex中
- 跟其他Series一样,不同索引的时间序列之间的算术运算会自动按日期对齐
- pandas用Numpy的datetime64数据类型以纳秒形式存储时间戳。
1 索引、选取、子集构造
- 由于TimeStamp是Series的一个子类,所以在索引以及数据选取方面它们的行为是一样的。
- 有一种更为简便的用法:直接传入一个可以被解释为日期的字符串。
- 对于较长的时间序列,只需传入“年”或“年月”即可轻松选取数据的切片。
- 通过日期进行切片的方式只对规则Series有效。
- 由于大部分时间序列数据都是按照时间先后排序的,因此也可以用不存在于该时间序列中的时间戳对齐进行切片(即范围查询)。此外,还有两个等价的实例方法可以截取两个日期之间的TimeSeries,after = ‘1/9/2011’,before。
- 这些操作对DataFrame也有效。
2 带有重复索引的时间序列
- 在某些应用场景中,可能会存在多个观测数据落在同一个时间点上的情况,通过检查索引的is_unique属性,可以知道是否唯一。
- 想要对具有唯一时间戳的数据进行聚合,一个办法是使用groupby,并传入level = 0(索引的唯一一层)。
四 日期的范围、频率及移动
- pandas中的时间序列一般被认为是不规则的,也就是说,没有固定的频率。对于大部分应用程序而言,这是无所谓的。但是,它常常需要以某种相对固定的频率进行分析,比如每日、每月、每15分钟(这样自然会在时间序列中引入缺失值)、幸运的是pandas有一整套标准时间序列频率以及用于重采样、频率推断、生成固定频率日期范围的工具。例如:将一个时间序列转换为一个具有固定频率的时间序列,只需调用resample即可。
1 生成日期范围
- pandas.date_range可用于生成指定长度的DatetimeIndex
index = pd.date_range('4/1/2012','6/1/2012')
- 默认情况下,date_range会产生按天计算的时间点。如果只传入起始或者结束日期,就还得传入一个表示一段时间的数字。
pd.date_range('4/1/2012','6/1/2012',periods = 20)
- 起始和结束日期定义了日期索引的严格边界。例如:如果想要生成一个由每月最后一个工作日组成的日期索引,可以传入“BM”频率,这样就只会包含时间间隔内(或刚好在边界上)符合频率要求的日期。
pd.date_range('4/1/2012','6/1/2012',freq = 'BM')
- date_range默认会保留起始和结束时间戳的时间信息(如果有的话)。
- 有时,虽然起始和结束日期带有时间信息,但希望产生一组被规范化到午夜的时间戳。normalize可以实现该功能。
pd.date_range('5/2/2012 12:56:31' ,periods = 5,normalize = True)
2 频率和日期偏移量
- pandas中的频率是由一个基础频率(base frequency)和一个乘数组成。基础频率通常以一个字符串别名组成,比如‘M’表示每月,“H”表示每时。对于每一个基础频率,都有一个呗成为日期偏移量(date offset)的对象与之对应。
from pandas.tseries.offset import Hour,Minute
hour = Hour()
hour = Hour(4) # 传入一个整数即可定义偏移量的倍数
- 一般来说,无需显示创建这样的对象,只需使用诸如“H”或“4H”这样的字符串别名即可。在基础频率前面放一个整数即可创建倍数。
- 大部分偏移量都可以通过加法连接。
- 同理,也可以传入频率字符串(如:2h30min),这种频率可以被高效地解析为等效表达式。
pd.date_range('1/1/2012',periods = 20,freq = '1h30min')
- 有些频率所描述的时间点并不是均匀分隔的。锚点偏移量。
- 时间序列的基础频率:
- D # day 每日历日
- B # businessday 每工作日
- H # hour 每小时
- T或min # minute 每分钟
- S # second 每秒
- L或ms # milli 每毫秒
- U # 每微妙
- M # 每月最后一个日历日
- BM # 每月最后一个工作日
- MS # 每月第一个日历日
- BMS # 每月第一个工作日
- W-MON/W-TUE… # 从指定的星期几开始算起、每周
- WOM-1MON… # 产生每月第一个、二、三个星期几
- Q-JAN/Q-FEB… # 对于以指定月份结束的年度,每季度最后一月的最后一个 日历日
- BQ-JAN # 对于以指定月份结束的年度,每季度最后一月的最后一个 工作日
- QS-JAN# 对于以指定月份结束的年度,每季度最后一月的第一个 日历日
- BQS-JAN# 对于以指定月份结束的年度,每季度最后一月的第一个 日历日
- A-JAN # 每年指定月份的最后一个日历日
- BA-JAN # 每年指定月份的最后一个工作日
- AS-JAN # 每年指定月份的第一个日历日
- BAS-JAN # 每年指定月份的第一个工作日
3 移动(超前和滞后)数据
- 移动(shifting)指的是沿着时间轴将数据前移或后移。
- shift同行用于计算一个时间序列或多个时间序列中的百分比变化
- 通过偏移量对日期进行位移。
五 时区处理
1 本地化和转换
2 操作时区意识型Timestamp对象
3 不同时区之间的运算
六 时期及其算术运算
1 时期的频率转换
2 按季度计算的时期频率
3 将Timestamp转换为Period(及其反向过程)
4 通过数组创建PeriodIndex
七 重采样及频率转换
- 重采样指的是将时间序列从一个频率转换到另一个频率的处理过程。将高频率数据聚合到低频率成为降采样,而将低频率数据转换到高频率则成为升采样。
- pandas对象都带有一个resample方法,它是各种频率转换工作的主力函数。
- resample方法的参数:
- freq # 表示重采样频率的字符串或DateOffset
- how = ‘mean’ # 用于产生聚合值的函数名或数组函数
- axis = 0 # 重采样的轴
- fill_method = None # 升采样时如何插值
- closed = ‘right’ # 在降采样中,各时间段的哪一段是闭合的
- label = ‘right’# 在降采样中,如何设置聚合值的标签
- loffset = None # 面元标签的时间校正值
- limit = None # 在前向或后向填充时,允许填充的最大时期数
- kind = None # 聚合到时期或时间戳,默认聚合到时间序列的索引类型
- convention = None # 当重采样时期时,将低频率转换到高频率所采用的约定
1 降采样
- 将数据聚合到规整的低频率是一件非常普通的额时间序列处理任务。待聚合的数据不必拥有固定的频率,期望的频率会自动定义聚合的面元边界,这些面元用于将时间序列拆分为多个片段。
- 用resample对数据进行降采样时,需要考虑两样东西:
- 各区间哪边是闭合的
- 如何标记各个聚合面元,用区间的开头还是结尾
rng = pd.date_range('1/1/2012',periods = 12,freq = 'T')
ts = Series(np.range(12),index = rng)
ts.resample('5min',how = 'sum')
ts.resample('5min',how = 'sum',closed = 'left') # 传入label = 'left'即可用面元的左边界进行标记
ts.resample('5min',how = 'sum',loffset = '-1s') # 通过loffset设置一个字符串或日期偏移量即可实现从右边界或左边界减去或加上一个时间以便更明白该时间戳到底表示的是哪个区间。
- 另一种降采样的方法是pandas的groupby功能。
2 升采样和插值
- 将数据从低频率转换到高频率时,就不需要聚合了,会引入缺失值,需要用到fillna和reindex
3 通过时期进行重采样
- 对采用时期索引的数据进行重采样是件非常简单的事情。升采样要稍微麻烦点,必须决定在新频率中各区间的哪段用于放置原来的值。
- 由于时期指的是时间区间,所以升采样和降采样的规则比较严格:
- ① 在降采样中,目标频率必须是源频率的子时期
- ② 在升采样中,目标频率必须是源频率的超时期
- 如果不满足这些条件,就会引发异常。
八 时间序列绘图
- 当对DataFrame调用plot时,所有时间序列都被绘制在一个subplot上,并有一个图例说明哪个是哪个。
- pandas时间序列在绘图方面还有一个特点,当右键点击并拖拉(放大、缩小)时,日期会动态展开或收缩,且绘图窗口中的时间区间会被重新格式化。当然,只有在交互模式下使用matplotlib才会有此效果。
九 移动窗口函数
- 在移动窗口(可以带有指数衰减权数)上计算的各种统计函数也是一类常见于时间序列的数组变换。成为移动窗口函数,其中还包括那些窗口不定长的函数(如指数加权移动平均)。跟其他函数一样,移动窗口函数也会自动排除缺失值。
- 诸如rolling_meaning 这样的函数需要指定数量的非NA观测值。可以修改该行为以解决缺失数据的问题。
- 要计算扩展窗口平均,可以将扩展窗口看做一个特殊的窗口,其长度与时间序列一样,但只需一期即可计算一个值。
- 对DataFrame调用rolling_mean会将转换应用到所有的列上。
- 移动窗口和指数加权函数
- rolling _count
- rolling_sum
- rolling_mean
- rolling_median
- rolling_var/rolling_std
- rolling_skew/rolling_kurt
- rolling_min/rolling_max
- rolling_quantile
- rolling_corr/rolling_cov
- rolling_apply
- ewma
- ewmvar/ewmstd
- ewmcorr/ewmcov
1 指数加权函数
- 另一种使用固定大小窗口及相等数观测值的办法是,定义一个衰减因子常量,以便使近期的观测值拥有更大的权数。
- 由于指数加权统计会赋予近期的观测值更大的权数,因此相对于等权统计,它能适应更快的变化。
2 二元移动函数
- 有些统计运算(如相关系数与协方差)需要在两个以上的时间序列上执行。
- 假设需要一次性计算多只股票的标准普尔500指数的相关系数。只需要传入一个TimeSeries和一个DataFrame,rolling_corr就会自动计算TimeSeries与DataFrame各列的额相关系数。
3 用户自定义的移动窗口函数
- rolling_apply函数使用户能够在移动窗口上应用自己设计的数组函数。唯一要求就是:该函数要能从数组的各个片段中产生单个值(即简约)。