"Pandas时间序列基本处理"

  "Pandas时间序列基本处理"

Posted by Kakarotto on April 3, 2017

学习笔记–pandas时间序列的运用

pandas标准库里包含有日期和时间数据的数据类型,主要模块是: datetime,time,calendar

from datetime import datetime

一、时间的运算和格式

输出时间

now=datetime.now()
now.year,now.month,now.day

算时间差

delta=datetime(2011,11,7)-datetime(2008,6,24,8,15)
delta.days
delta.seconds
#delta输出的格式是datetime.timedelta(a,b,c) 分别代表日、秒、毫秒

时间运算


start=datetime(2010,1,1)
start+timedelta(12)
start-2*timedelta(12)

二、字符串和datetime的转换

strstrftimestrptime可以相互转化datetime对象和字符串

stmap=datetime(2017,1,1)
#按照默认的格式转换为字符串
string=str(stmap)
#按照指定的格式转化为字符串(注意Y是大写)
string=stmap.strftime('%Y-%m-%d')
#字符串按照指定的格式转换为datetime
datetime.strptime(string,'%Y-%m-%d')
datetime.datetime(2017,1,1,0,0)
from dateutil.parser import parse
#通过第三方库转换字符串为datetime格式
parse('2017-1-1')
#将月放在最前的datetime格式转换
parse('6/12/2011',dayfirst=True)
#pandas中多处理成组日期的转换
datestrs=['2017-1-1','2017-2-2']
a=pd.to_datetime(datestrs)

三、时间序列基础

pandas最基本的时间序列类型就是以时间戳(datetime)为索引的Series

#生成时间序列
dates=[datetime(2017,1,1),datetime(2017,1,2),datetime(2017,1,3)]
ts=Series(np.random.randn(3),index=dates)
type(ts)
ts.index

不同索引的时间序列之间的算数运算会自动按照时间对齐: (这个是pandas作为金融上时间序列分析最基本的用处)

ts+ts[::2]

四、时间序列的索引和选取

实际上timeseries类型是Series的一个子类。Series的方法均适用于ts类型,所以后面要讨论的是时间序列类型自身的特殊索引方式。

#按照日子字符串索引
ts['2017/1/1']
#构造连续时间的时间序列
ts=Series(np.random.randn(100),index=pd.date_range('1/1/2017',periods=100))
#查看所有2017年的
ts['2017']
#查看所有2017年1月的
ts['2017-1']
#通过日期进行连续切片
ts[datetime(2017,3,1):]
#进行范围查询
ts[datetime(2017,3,1):datetime(2018,1,1)]

注意:该方法得到的东西也是视图而不是拷贝

上述操作对DateFrame操作同样适用

dates=pd.date_range('1/1/2017',periods=100)
df=DataFrame(np.random.randn(100,4),index=dates,columns=['a','b','c','d'])
df.ix['2017-4']

五、带有重复索引的时间序列

dates=pd.DatetimeIndex(['1/1/2017','1/2/2017','1/3/2017','1/1/2017'])
ts=Series(np.arange(4),index=dates)
#判断是时间索引是否唯一
ts.index.is_unique
#取整合不唯一项
grouped=ts.groupby(level=0)
#按平均数整合
grouped.mean()
#按条数整合
grouped.count()

六、日期的范围、频率操作

生成日期

index=pd.date_range('1/1/2017','4/1/2017')
index=pd.date_range('1/1/2017',periods=100)
index=pd.date_range(end='1/1/2017',periods=100)

上面的日期生成是连续生成,我们可以按照一定频率取生成日期

#BM表示生成频率是每个月的最后一天
index=pd.date_range('1/1/2017','4/1/2017',freq='BM')

日期的偏移量

from pandas.tseries.offsets import Hour,Minute
pd.date_range('1/1/2017','1/3/2017',freq='1h')
pd.date_range('1/1/2017','1/3/2017',freq='1h30min')
pd.date_range('1/1/2017','12/1/2017',freq='WOM-1FRI')

更多的时间频率类见书p315

七、移动数据和时间

移动数据

ts=Series(np.random.randn(4),index=pd.date_range('1/1/2017',periods=4,freq='M'))
#数据往后移
ts.shift(2)
#数据往前移
ts.shift(-4)

一般shift的操作用于求时间序列中的百分比变化

移动时间

#对时间戳进行移动,时间戳向后移动
ts.shift(2,freq='M')
ts.shift(2,freq='3D')

八、时期及其算术运算

时期的概念和时间不同,时间表示的是一个点,时期表示的是一个时间区间。

#表示2017年整段时间
p=pd.Period(2017,freq='A-DEC')
#表示几个时期,每个时期的长度为一个月
rng=pd.period_range('1/1/2017','5/1/2017',freq='M')
#生成以时期为索引的series
obj=Series(np.random.randn(5),index=rng)

时期频率的转换

p=pd.Period('2007',freq='A-DEC')
p.asfreq('M',how='start')
p.asfreq('M',how='end')
p=pd.Period('2007',freq='A-JUN')
p.asfreq('M','start')
p.asfreq('M','end')
#这里书上输出有错
#这里意思是2007年一年的时期,从2017年6月结束,那么上一级开始是2016年7月
p=pd.Period('2007-08','M')
p.asfreq('A-JUN')
#正因为上面原因,在高转低频率的时候,归属会出现变化

时期和时间的转换

rng=pd.date_range('1/1/2000',periods=3,freq='M')
ts=Series(randn(3),index=rng)
#将时间的时间序列转化为时期索引
pts=ts.to_period()
##取每个月末尾转换为时间戳
pts.to_timestamp(how='end')

九、重采样和频率转换

重采样指的就是将时间序列从一个频率转换到另一个频率的过程。

rng=pd.date_range('1/1/2017',periods=100,freq='D')
ts=Series(randn(100),index=rng)
#频率改为月,采用平均值的方式
ts.resample('M',how='mean')
#频率改为月,输出的方式是时期
ts.resample('M',how='mean',kind='period')

降采样主要注意三个问题

  1. closed=’left’ or ‘right’
  2. label =’left’ or ‘right’
  3. 聚合的方式是什么
rng=pd.date_range('1/1/2017',periods=12,freq='T')
ts=Series(np.arange(12),index=rng)
ts.resample('5min',how='sum',closed='left',label='left')
#OHLC采样
te.resample('5min',how='ohlc')

升采样和插值

frame=DataFrame(np.random.randn(2,4),index=pd.date_range('1/1/2017',periods=2,freq='W-WED'),columns=['1','2','3','4'])
#对缺失值进行插值处理
frame.resample('D',fill_method='ffill')

通过时期进行重采样

#时期的降采样
frame=DataFrame(np.random.randn(24,4),index=pd.period_range('1-2000','12-2001',freq='M'),columns=['a','b','c','d'])
frame1=frame.resample('A-DEC',how='mean')
#时期的降采样
frame1.resample('Q-DEC',fill_method='ffill')

注意:在降采样中。目标频率必须是源频率的子时期。在升采样中,目标频率必须是源频率的超时期。

十、时间序列的简单画图

import matplotlib.pyplot as plt
from numpy.random import randn
import numpy as np
from pandas import Series,DataFrame
import pandas
frame=DataFrame(np.random.randn(365,3),index=pd.date_range('1/1/2017','12/31/2017',freq='D'),columns=['a','b','c'])
fig=plt.figure()
ax1=fig.add_subplot(2,1,1)
ax2=fig.add_subplot(2,1,2)
frame['a'].plot(ax=ax1)
frame['b'].plot(ax=ax2)

10