不管在哪个领域中(如金融学、经济学、生态学、神经科学、物理学等),时间序列(time series)数据都是一种重要的结构化数据形式。在多个时间点观察或测量到的任何事物都可以形成一段时间序列。很多时间序列都是固定频率的,也就是说,数据点是根据某种规律定期出现的(比如每15秒、每5分钟、每个月出现一次)。时间序列也可以是不定期的。时间序列数据的意义取决于具体的应用场景,主要有以下几种:
python标准库包含用于日期(date)和时间(time)数据的数据类型,而且还有日历方面的功能。主要用到的模块:datetime、time以及calendar模块。
代码示例:
from datetime import datetime
from datetime import timedelta
#毫秒形式存储日期和时间
#datetime(year, month, day, hour, minute, second, microsecond)
now = datetime.now() #now=datetime.datetime(2018, 4, 10, 16, 56, 29, 739397)
#datetime.timedelta表示两个datetime对象之间的时间差
#timedelta(days,seconds)
delta = datetime(2018, 4, 10) - datetime(2017, 7, 1, 1, 20)
#delta= datetime.timedelta(282, 81600)
#给datetime对象加/减上timedelta
start = datetime(2018, 1, 1)
start + timedelta(12) #result:datetime.datetime(2018, 1, 13, 0, 0)
start - 2 * timedelta(12) #result:datetime.datetime(2017, 12, 8, 0, 0)
字符串与datatime之间的相互转换
datetime中格式定义(英语系统下):
代码示例:
from dateutil.parser import parse
import pandas as pd
#字符串与datetime对象的转换
#datetime对象转换为字符串
stamp = datetime(2018, 1, 1)
#第一种str方法
str(stamp) #'2018-01-01 00:00:00'
#第二中strftime
stamp.strftime('%Y-%m-%d')
#字符串对象转换为datetime,利用strptime
#strptime通过已知格式进行日期解析的最佳方法
value = '2018-01-01' #'2018-01-01'
datetime.strptime(value, '%Y-%m-%d')
#parser.parse方法进行日期解析,可以解析几乎所有日期表现形式。
parse('2018-01-01') #datetime.datetime(2018, 1, 1, 0, 0)
parse('Jan 01, 2018 6:45 PM') #datetime.datetime(2018, 1, 1, 18, 45)
#parse解析字符串时,默认月在前,日在后
parse('6/12/2011') # datetime.datetime(2011, 6, 12, 0, 0)
#因此,对于日在前,月在后的,可以设置 dayfirst=True
parse('6/12/2011', dayfirst=True) #datetime.datetime(2011, 12, 6, 0, 0)
#to_datetime可以解析多种不同的日期表现形式
datestrs = ['2018-01-01 12:00:00', '2018-02-22 00:00:00']
pd.to_datetime(datestrs)
#DatetimeIndex(['2018-01-01 12:00:00', '2018-02-22 00:00:00'], dtype='datetime64[ns]', freq=None)
#还可以处理缺省值(空字符串或None)
idx = pd.to_datetime(datestrs + [None])
#idx=DatetimeIndex(['2018-01-01 12:00:00', '2018-02-22 00:00:00', 'NaT'], dtype='datetime64[ns]', freq=None)
#注意:日期中的缺省值是NaT(Not a Time)
pd.isnull(idx) #array([False, False, True], dtype=bool)
二、世界序列基础
pandas最基础的时间序列类型就是以时间戳(通常以python字符串或datetime对象表示)为索引的Series。
主要两部分:
#索引、选取、子集构造
#索引
#方法1,传入一个Timestamp对象
stamp = ts.index[0] #stamp=Timestamp('2018-01-02 00:00:00')
ts[stamp] # -0.10607355595045509
#传入一个可以被解释为日期的字符串
ts['1/10/2018'] #-1.5461476964186704
ts['20180110'] #-1.5461476964186704
#切片
#对于较长的时间序列,通过传入“年”、“年月”即可轻松选取数据切片
longer_ts = pd.Series(np.random.randn(1000),
index=pd.date_range('1/1/2018', periods=1000))
longer_ts['2018']
longer_ts['2018-03']
#通过日期进行切片的方式只对规则的Series有效
ts[datetime(2018, 1, 10):]
"""ts: ts[datetime(2018, 1, 10):]:
2018-01-02 -0.106074 2018-01-10 -1.546148
2018-01-03 0.100822 2018-01-13 0.141358
2018-01-06 -0.894717 dtype: float64
2018-01-08 -0.498678
2018-01-10 -1.546148
2018-01-13 0.141358
dtype: float64
"""
#时间序列大部分按时间先后顺序排列,可以使用不存在该时间序列的时间戳来进行切片(即:查询范围)
ts['1/5/2018':'1/15/2018']
"""
2018-01-06 -0.894717
2018-01-08 -0.498678
2018-01-10 -1.546148
2018-01-13 0.141358
dtype: float64
"""
#截取两个日期之间的TimeSeries
#截取2018-1-9之前的徐磊
ts.truncate(after='1/9/2018')
"""
2018-01-02 -0.106074
2018-01-03 0.100822
2018-01-06 -0.894717
2018-01-08 -0.498678
dtype: float64
"""
#对于DataFrame对象同样有用,时间点只取周三(freq='W-WED')
dates = pd.date_range('1/1/2018', periods=100, freq='W-WED')
long_df = pd.DataFrame(np.random.randn(100, 4),
index=dates,
columns=['Colorado', 'Texas',
'New York', 'Ohio'])
long_df.loc['3-2018']
"""
Colorado Texas New York Ohio
2018-03-07 0.903078 -0.931066 0.213840 0.169752
2018-03-14 1.874872 -0.682288 -0.820822 -0.451576
2018-03-21 0.381608 -0.493432 0.284216 0.353538
2018-03-28 -0.412199 0.102380 -0.363941 -1.693375
"""
#带重复索引的时间序列
dates = pd.DatetimeIndex(['1/1/2018', '1/2/2018', '1/2/2018',
'1/2/2018', '1/3/2018'])
dup_ts = pd.Series(np.arange(5), index=dates)
"""dup_ts=
2018-01-01 0
2018-01-02 1
2018-01-02 2
2018-01-02 3
2018-01-03 4
dtype: int32
"""
#利用is_unique属性查询是否唯一
dup_ts.index.is_unique # False
#索引时,如果索引重复,则产生标量值,反之,则产生切片
dup_ts['1/3/2018'] # 索引不重复,4
dup_ts['1/2/2018'] # 索引重复的
"""
2018-01-02 1
2018-01-02 2
2018-01-02 3
dtype: int32
"""
#对非唯一时间戳进行聚合,并传入level=0(索引的唯一一层!)
grouped = dup_ts.groupby(level=0)
grouped.mean()
grouped.count()
"""
grouped.mean(): grouped.count():
2018-01-01 0 2018-01-01 1
2018-01-02 2 2018-01-02 3
2018-01-03 4 2018-01-03 1
"""
附:时间序列的基础频率一览表: