教你用Pandas玩转时间序列数据

微信公众号:「Python读财」
如有问题或建议,请公众号留言

进行金融数据分析或量化研究时,总避免不了时间序列数据的处理,时间序列是指在一定时间内按时间顺序测量的某个变量的取值序列。常见的时间序列数据有一天内随着时间变化的温度序列,又或者交易时间内不断波动的股票价格序列。Pandas也因其强大的时序处理能力而被广泛应用于金融数据分析,这篇文章为大家介绍一下Pandas中的时间序列处理,所使用的数据是上证指数2019年的行情数据。

数据.png

时间相关的数据类型

Pandas时序处理中最常见的两种数据类型为datetimetimedelta。一个datetime可以如下图所示:

datetime.png

datetime顾名思义就是既有日期date也有时间time,表示一个具体的时间点(时间戳)。timedelta则表示两个时间点之间的差,比如2020-01-012020-01-02之间的timedelta即为一天,相信并不难理解。

将时间列转换为时间格式

大多数时候,我们是从csv文件中导入数据,此时Dataframe中对应的时间列是字符串的形式,如下:

In [5]: data.trade_date.head()
Out[5]:
0    20190102
1    20190103
2    20190104
3    20190107
4    20190108
Name: trade_date, dtype: object

运用pd.to_datetime(),可以将对应的列转换为Pandas中的datetime64类型,便于后期的处理

In [11]: data["trade_date"] = pd.to_datetime(data.trade_date)

In [12]: data.trade_date.head()
Out[12]:
0   2019-01-02
1   2019-01-03
2   2019-01-04
3   2019-01-07
4   2019-01-08
Name: trade_date, dtype: datetime64[ns]

时间序列的索引

时间序列中索引和Pandas普通的索引类似,大多时候调用.loc[index,columns]进行相应的索引,直接上代码看看

In [20]: data1 = data.set_index("trade_date")

# 2019年6月的数据
In [21]: data1.loc["2019-06"].head()
Out[21]:
                close       open       high        low
trade_date
2019-06-03  2890.0809  2901.7424  2920.8292  2875.9019
2019-06-04  2862.2803  2887.6405  2888.3861  2851.9728
2019-06-05  2861.4181  2882.9369  2888.7676  2858.5719
2019-06-06  2827.7978  2862.3327  2862.3327  2822.1853
2019-06-10  2852.1302  2833.0145  2861.1310  2824.3554

# 2019年6月-2019年8月的数据
In [22]: data1.loc["2019-06":"2019-08"].tail()
Out[22]:
                close       open       high        low
trade_date
2019-08-26  2863.5673  2851.0158  2870.4939  2849.2381
2019-08-27  2902.1932  2879.5154  2919.6444  2879.4060
2019-08-28  2893.7564  2901.6267  2905.4354  2887.0115
2019-08-29  2890.9192  2895.9991  2898.6046  2878.5878
2019-08-30  2886.2365  2907.3825  2914.5767  2874.1028

提取出时间/日期的属性

在时序数据处理过程中,经常需要实现下述需求:

  • 求某个日期对应的星期数(2019-06-05是第几周)
  • 判断一个日期是周几(2020-01-01是周几)
  • 判断某一日期是第几季度(2019-07-08属于哪个季度)

……

当你数据中的时间列(本数据中为trade_date列)已经转换为datetime64格式时,仅需调用.dt接口,即可快速求得想要的结果,下表中列出了.dt接口所提供的常见属性:

dt表.png

具体演示一下(下面仅显示2019-01-02的信息):

# 一年中的第几天
In [13]: data.trade_date.dt.dayofweek[0]
Out[13]: 2

# 返回对应日期
In [14]: data.trade_date.dt.date[0]
Out[14]: datetime.date(2019, 1, 2)

# 返回周数
In [15]: data.trade_date.dt.weekofyear[0]
Out[15]: 1

# 返回周几
In [16]: data.trade_date.dt.weekday_name[0]
Out[16]: 'Wednesday'

resample

resample翻译过来是重采样的意思,官方文档中是这么描述resample

resample() is a time-based groupby

翻译过来就是基于时间groupby操作,我个人认为这是Pandas时间序列处理中最重要的功能,也是本文的重中之重。

根据采样是从低频到高频还是从高频到低频可以分为升采样降采样两种方式,先来看看降采样是啥

  • 降采样

以一个实例来引入,我们使用的数据是上证指数2019年的日级别数据,如果现在想求每季度的平均收盘价,应该怎么操作呢?

从日级别数据求季度级别数据,是从高频到低频聚合操作,其实就类似于groupby按季度进行操作,用resample来写是这样子

In [32]: data.resample('Q',on='trade_date')["close"].mean()
Out[32]:
trade_date
2019-03-31    2792.941622
2019-06-30    3010.354672
2019-09-30    2923.136748
2019-12-31    2946.752270
Freq: Q-DEC, Name: close, dtype: float64

其中'Q'是以季度为频率进行采样,on指定datetime列(如果索引为Datetimeindex,则on不需要指定,默认依据索引进行降采样)。整个过程图解如下:

降采样.png

整个过程其实就是一个groupby过程:

  • 对原有的数据按照指定的频率进行切分,分到不同的group
  • 对不同的group执行操作
  • 整合操作结果

其中,切分的频率可以为任何时间频率,可以为季度Q、月度M、星期W、N天ND,也可以为时H、分T,当然,如果切分后的频率小于原有的时间频率,就是我们下面要讲的升采样。

  • 升采样

当采样的频率低于原有的频率时,即为升采样。升采样是对原有的时间粒度更为细粒度的划分,所以升采样时会产生缺失值。下面取2019-01-022019-01-03的数据按照6H的频率演示一下:

In [24]: example
Out[24]:
                close
trade_date
2019-01-02  2465.2910
2019-01-03  2464.3628

In [25]: example.resample('6H').asfreq()
Out[25]:
                         close
trade_date
2019-01-02 00:00:00  2465.2910
2019-01-02 06:00:00        NaN
2019-01-02 12:00:00        NaN
2019-01-02 18:00:00        NaN
2019-01-03 00:00:00  2464.3628

resample后的结果应用.asfreq()会返回新频率下的结果。可以看到升采样后产生了缺失值。如果想要填充缺失值可以采用向后填充.bfill()或向前填充.ffill()的方式:

# 向前填充,缺失值取2465.2910进行填充
In [29]: example.resample('6H').ffill()
Out[29]:
                         close
trade_date
2019-01-02 00:00:00  2465.2910
2019-01-02 06:00:00  2465.2910
2019-01-02 12:00:00  2465.2910
2019-01-02 18:00:00  2465.2910
2019-01-03 00:00:00  2464.3628

# 向后填充,缺失值取2464.3628进行填充
In [30]: example.resample('6H').bfill()
Out[30]:
                         close
trade_date
2019-01-02 00:00:00  2465.2910
2019-01-02 06:00:00  2464.3628
2019-01-02 12:00:00  2464.3628
2019-01-02 18:00:00  2464.3628
2019-01-03 00:00:00  2464.3628

总结一下resampleresample可以对原有的时间序列进行任何频率freq的采样,如果从低频到高频为升采样,高频到低频为降采样。整个操作过程和groupby基本一致,所以也可以对resample后的对象进行applytransform等操作,具体操作和原理这里就不多解释了,类比于groupby即可,参看这篇文章Pandas数据分析——超好用的Groupby详解

扫码关注公众号 「Python读财」,第一时间获取干货!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,451评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,172评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,782评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,709评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,733评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,578评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,320评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,241评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,686评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,878评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,992评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,715评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,336评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,912评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,040评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,173评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,947评论 2 355

推荐阅读更多精彩内容