Pandas基础(十一)时间序列
pandas提供了一套标准的时间序列处理工具和算法,使得我们可以非常高效的处理时间序列,比如切片、聚合、重采样等等。
本节我们讨论以下三种时间序列:
- 时间戳(time stamp):一个特定的时间点,比如2018年4月2日。
- 时间间隔和时期(time period):两个特定的时间起点和终点,比如2018年4月2日-2019年4月2日。
- 时间差或持续时间(time deltas):特定的时间长度,比如20秒。
Python的时间序列处理是一个很重要的话题,尤其在金融领域有着非常重要的应用。本节只做简单的介绍,如果以后有需要的话再深入学习。本文参考的Working with Time Series对python原生的日期时间处理模块datetime,numpy日期时间处理模块datetime64,以及第三方日期时间处理模块dateutil等都做了介绍,我们这里跳过这些,直接进入pandas的时间序列。
import numpy as npimport pandas as pd
1. pandas时间序列:时间索引
当你使用时间戳作为数据索引的时候,pandas的时间序列工具就变得是非有用。
index = pd.DatetimeIndex(['2014-07-04', '2014-08-04','2015-07-04', '2015-08-04'])data = pd.Series([0, 1, 2, 3], index=index)data#> 2014-07-04 0#> 2014-08-04 1#> 2015-07-04 2#> 2015-08-04 3#> dtype: int64data['2014-07-04':'2015-07-04']#> 2014-07-04 0#> 2014-08-04 1#> 2015-07-04 2#> dtype: int64data['2015']#> 2015-07-04 2#> 2015-08-04 3#> dtype: int64
2. pandas时间序列数据结构
对于时间戳,pandas提供了
Timestamp类型。它基于numpy.datetime64数据类型,与与之相关的索引类型是DatetimeIndex。对于时间时期,pandas提供了
Period类型,它是基于numpy.datetime64编码的固定频率间隔。与之相关的索引类型是PeriodIndex。对于时间差,pandas提供了
Timedelta类型,同样基于numpy.datetime64。与之相关的索引结构是TimedeltaIndex。
最基本的时间/日期是时间戳Timestamp和DatetimeIndex。但是我们可以直接使用pd.to_datetime()函数来直接解析不同的格式。传入单个日期给pd.to_datetime()返回一个Timestamp,传入一系列日期默认返回DatetimeIndex。
dates = pd.to_datetime([datetime(2015, 7, 3), '4th of July, 2015','2015-Jul-6', '07-07-2015', '20150708'])dates#> DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-06', '2015-07-07',#> '2015-07-08'],#> dtype='datetime64[ns]', freq=None)
当一个日期减去另一个日期的时候,TimedeltaIndex就会被创建:
dates - dates[0]#> TimedeltaIndex(['0 days', '1 days', '3 days', '4 days', '5 days'], dtype='timedelta64[ns]', freq=None)
2.1 定期序列
为了方便地创建定期的日期序列,pandas提供了一些函数:pd.date_range()创建时间戳,pd.period_range()创建时期,pd.timedelta_range()创建时间差。默认情况下频率间隔是一天。
pd.date_range('2015-07-03', '2015-07-10')#> DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-05', '2015-07-06',#> '2015-07-07', '2015-07-08', '2015-07-09', '2015-07-10'],#> dtype='datetime64[ns]', freq='D')
另外可以不指定终点,而是提供一个时期数:
pd.date_range('2015-07-03', periods=8)#> DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-05', '2015-07-06',#> '2015-07-07', '2015-07-08', '2015-07-09', '2015-07-10'],#> dtype='datetime64[ns]', freq='D')
频率间隔可以通过freq参数设置,默认是D:
pd.date_range('2015-07-03', periods=8, freq='H')#> DatetimeIndex(['2015-07-03 00:00:00', '2015-07-03 01:00:00',#> '2015-07-03 02:00:00', '2015-07-03 03:00:00',#> '2015-07-03 04:00:00', '2015-07-03 05:00:00',#> '2015-07-03 06:00:00', '2015-07-03 07:00:00'],#> dtype='datetime64[ns]', freq='H')
类似的
pd.period_range('2015-07', periods=8, freq='M')#> PeriodIndex(['2015-07', '2015-08', '2015-09', '2015-10', '2015-11', '2015-12',#> '2016-01', '2016-02'],#> dtype='period[M]', freq='M')pd.timedelta_range(0, periods=10, freq='H')#> TimedeltaIndex(['00:00:00', '01:00:00', '02:00:00', '03:00:00', '04:00:00',#> '05:00:00', '06:00:00', '07:00:00', '08:00:00', '09:00:00'],#> dtype='timedelta64[ns]', freq='H')
3. 频率和偏移
以上这些时间序列处理工具最基础的概念是频率和时间偏移。下表总结了主要的代码表示:
| 代码 | 描述 | 代码 | 描述 |
|---|---|---|---|
D |
日历天 | L |
厘秒 |
W |
星期 | U |
毫秒 |
M |
月末 | N |
纳秒 |
Q |
季度末 | B |
工作日 |
A |
年末 | BM |
工作月末 |
H |
小时 | BQ |
工作季末 |
T |
分钟 | BA |
工作年末 |
S |
秒 | BH |
工作时 |
上面的月,季度以及周期性频率都被标记为这一时期的终点,如果想变成起始点可以加S后缀。
| 代码 | 描述 | 代码 | 描述 |
|---|---|---|---|
MS |
月初 | BMS |
工作月初 |
QS |
季度初 | BQS |
工作季初 |
AS |
年初 | BAS |
工作年初 |
另外,还可以通过加后缀的方法改变季度或年的月份等。
Q-JAN,BQ-FEB,BQS-APR等等;A-JAN,BA-FEB,BAS-APR等等。类似的,星期也可以分解成周一,周二…
W-SUN,W-MON,W-WED等等以上这些代码还可以与数字结合来表示频率, 例如我们要表示2小时30分的频率:
pd.timedelta_range(0, periods=9, freq="2H30T")#> TimedeltaIndex(['00:00:00', '02:30:00', '05:00:00', '07:30:00', '10:00:00',#> '12:30:00', '15:00:00', '17:30:00', '20:00:00'],#> dtype='timedelta64[ns]', freq='150T')
以上这些代码表示的含义还可以通过pd.tseries.offsets模块表示:
from pandas.tseries.offsets import BDaypd.date_range('2015-07-01', periods=5, freq=BDay())#> DatetimeIndex(['2015-07-01', '2015-07-02', '2015-07-03', '2015-07-06',#> '2015-07-07'],#> dtype='datetime64[ns]', freq='B')
更加详细的讨论可以看DateOffset。
4. 重采样,转移,加窗口
我们以一些真实的金融数据为例讲解,pandas-datareader(可通过conda install pandas-datareader来安装, 如果)包包含谷歌,雅虎等公司的金融数据。
from pandas_datareader import datagoog = data.DataReader('GOOG', start='2004', end='2016',data_source='google')goog.head()#> Open High Low Close Volume#> Date#> 2004-08-19 49.96 51.98 47.93 50.12 NaN#> 2004-08-20 50.69 54.49 50.20 54.10 NaN#> 2004-08-23 55.32 56.68 54.47 54.65 NaN#> 2004-08-24 55.56 55.74 51.73 52.38 NaN#> 2004-08-25 52.43 53.95 51.89 52.95 NaN
简单起见,我们只是用收盘价格
goog = goog['Close']
为了更好的说明问题,我们可以利用matplotlib对数据进行可视化,关于matplotlib可以通过Python for Data Analysis这本书进行学习,也可以通过官网的gallary进行学习,我个人当时是在官网看了大量的实例,有什么需求直接去官网找例子,都很方便。本系列学习笔记不会包含数据可视化部分。
import matplotlib.pyplot as pltgoog.plot()

4.1 重采样及频率转换
重采样(resampling)指的是将时间序列从一个频率转换到另一个频率的处理过程。将高频数据聚合到低频称为降采样(downsampling),将低频数据转换到高频则称为升采样(upsampling)。除此以外还存在一种采样方式既不是升采样,也不是降采样,比如W-WED转换成W-FRI。
可以通过resample()函数来实现,也可以通过更简单的方式asfreq()函数来实现。两者基本的不同点在于resample()是一种数据聚合方式asfreq()是一种数据选取方式。
goog.plot(alpha=0.5, style='-')goog.resample('BA').mean().plot(style=':')goog.asfreq('BA').plot(style='--');plt.legend(['input', 'resample', 'asfreq'],loc='upper left')

resample()的处理过程是取整年的数据的平均值,而asfreq()是选取年末的时间点的数据。
对于升采样来说,resample()与asfreq()是等效的。对于空置采样点都会用NaN来进行填充。就像pd.fillna()方法,asfreq()接受一个参数method可指定缺失值的填充方法。ffill表示与前面的值保持一致,bfill表示与后面的值保持一致等等。
fig, ax = plt.subplots(2, sharex=True)data = goog.iloc[:10]data.asfreq('D').plot(ax=ax[0], marker='o')data.asfreq('D', method='bfill').plot(ax=ax[1], style='-o')data.asfreq('D', method='ffill').plot(ax=ax[1], style='--o')ax[1].legend(["back-fill", "forward-fill"])

4.2 时间移动
另一个与时间序列相关的操作是数据在时间轴的移动。pandas提供了两个相关的函数:shift()和tshift(),两者的不同是shift()移动的是数据,tshift()移动的是时间轴(索引)。
fig, ax = plt.subplots(3, sharey=True)# apply a frequency to the datagoog = goog.asfreq('D', method='pad')goog.plot(ax=ax[0])goog.shift(900).plot(ax=ax[1])goog.tshift(900).plot(ax=ax[2])# legends and annotationslocal_max = pd.to_datetime('2007-11-05')offset = pd.Timedelta(900, 'D')ax[0].legend(['input'], loc=2)ax[0].get_xticklabels()[2].set(weight='heavy', color='red')ax[0].axvline(local_max, alpha=0.3, color='red')ax[1].legend(['shift(900)'], loc=2)ax[1].get_xticklabels()[2].set(weight='heavy', color='red')ax[1].axvline(local_max + offset, alpha=0.3, color='red')ax[2].legend(['tshift(900)'], loc=2)ax[2].get_xticklabels()[1].set(weight='heavy', color='red')ax[2].axvline(local_max + offset, alpha=0.3, color='red')

时移一个重要作用即使计算一段时间内的差别,比如计算谷歌股票一年的投资回报率:
ROI = 100 * (goog.tshift(-365) / goog - 1)ROI.plot()plt.ylabel('% Return on Investment')

4.3 滚动窗口
滚动统计是时间序列的又一重要的操作。可以通过Series和DataFrame的rolling()方法实现,返回类似于groupby的操作,同样也有许多数据聚合的操作。
rolling = goog.rolling(365, center=True)data = pd.DataFrame({'input': goog,'one-year rolling_mean': rolling.mean(),'one-year rolling_std': rolling.std()})ax = data.plot(style=['-', '--', ':'])ax.lines[0].set_alpha(0.3)

Pandas基础(十一)时间序列的更多相关文章
- Pandas基础学习与Spark Python初探
摘要:pandas是一个强大的Python数据分析工具包,pandas的两个主要数据结构Series(一维)和DataFrame(二维)处理了金融,统计,社会中的绝大多数典型用例科学,以及许多工程领域 ...
- 数据分析02 /pandas基础
数据分析02 /pandas基础 目录 数据分析02 /pandas基础 1. pandas简介 2. Series 3. DataFrame 4. 总结: 1. pandas简介 numpy能够帮助 ...
- 利用Python进行数据分析(12) pandas基础: 数据合并
pandas 提供了三种主要方法可以对数据进行合并: pandas.merge()方法:数据库风格的合并: pandas.concat()方法:轴向连接,即沿着一条轴将多个对象堆叠到一起: 实例方法c ...
- 利用Python进行数据分析(9) pandas基础: 汇总统计和计算
pandas 对象拥有一些常用的数学和统计方法. 例如,sum() 方法,进行列小计: sum() 方法传入 axis=1 指定为横向汇总,即行小计: idxmax() 获取最大值对应的索 ...
- 利用Python进行数据分析(8) pandas基础: Series和DataFrame的基本操作
一.reindex() 方法:重新索引 针对 Series 重新索引指的是根据index参数重新进行排序. 如果传入的索引值在数据里不存在,则不会报错,而是添加缺失值的新行. 不想用缺失值,可以用 ...
- 利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍
一.pandas 是什么 pandas 是基于 NumPy 的一个 Python 数据分析包,主要目的是为了数据分析.它提供了大量高级的数据结构和对数据处理的方法. pandas 有两个主要的数据结构 ...
- Bootstrap<基础十一>字体图标(Glyphicons)
字体图标(Glyphicons),并通过一些实例了解它的使用.Bootstrap 捆绑了 200 多种字体格式的字形. 获取字体图标 我们已经在 环境安装 章节下载了 Bootstrap 3.x 版本 ...
- Java基础(十一) Stream I/O and Files
Java基础(十一) Stream I/O and Files 1. 流的概念 程序的主要任务是操纵数据.在Java中,把一组有序的数据序列称为流. 依据操作的方向,能够把流分为输入流和输出流两种.程 ...
- numpy&pandas基础
numpy基础 import numpy as np 定义array In [156]: np.ones(3) Out[156]: array([1., 1., 1.]) In [157]: np.o ...
随机推荐
- jmeter时间格式化
jmeter时间格式化 #17位时间取到毫秒 ${__time(yyyyMMdd-HHmmssSSS,)} #10位时间戳 ${__time(/1000,)} yyyyMMddHHmmss yyyy年 ...
- csdn 站点使用
大学时使用csdn下载软件资源,最终csdn成为一个it中很重要站点,csdn的运营方式值得思考.
- centos安装ES(elasticsearch)
1.下载(版本为elasticsearch-6.5.4): https://www.elastic.co/downloads/elasticsearch 2.上传至服务/user/local目录 3. ...
- JAVA自学笔记18
JAVA自学笔记18 1.Map接口: 1)功能: 2) Map<String,String>m=new HashMap<String,String>(); //添加元素,元素 ...
- JSR 整理、翻译
https://jcp.org/en/jsr/all https://github.com/search?l=Java&q=JSR&type=Repositories
- Lua游戏开发之时区问题
目前大部分游戏都采用了Lua语言进行功能开发,在进行多语种发行的时候就会遇到时区显示的问题.以韩国版本为例,场景如下: 1.服务器处于固定的位置,比如放在首尔机房: 2.玩家所处的位置不确定,可能在韩 ...
- 根据javabean转换为mysql建表语句与mapper内容
原文地址: https://www.cnblogs.com/Jeffscnblog/p/10072483.html 一般上,我们会使用数据库表转换为javabean.dao.或是mapper,就叫逆 ...
- python3 HTTP Error 403:Forbidden
问题描述初学python,在用python中的urllib.request.urlopen()和urllib.request.urlretrieve方法打开网页时,有些网站会抛出异常: HTTP Er ...
- ubuntu 安装jdk 的两种方式:
:通过ppa(源) 方式安装. 2:通过官网下载安装包安装. 这里推荐第1种,因为可以通过 apt-get upgrade 方式方便获得jdk的升级 使用ppa/源方式安装 1.添加ppa sudo ...
- 命令 上传项目到git中
点击Clone or dowload会出现一个地址,copy这个地址备用. 接下来就到本地操作了,首先右键你的项目,如果你之前安装git成功的话,右键会出现两个新选项,分别为Git Gui Here, ...