利用Python进行数据分析5-时间序列

本文深入探讨了Python在时间序列分析中的应用,包括日期和时间数据类型、时间序列基础、日期范围、频率处理、时区转换、移动数据、时区处理、时期运算以及重采样等关键概念。时间序列在金融、经济等多个领域都有广泛应用,通过pandas库,可以高效处理和转换不同频率的数据,实现数据的聚合、插值和移动窗口统计。
摘要由CSDN通过智能技术生成

时间序列(time series)数据是⼀种重要的结构化数据形式,应⽤于多个领域,包括⾦融学、经济学、⽣态学、神经科学、物理学等。
时间序列数据的意义取决于具体的应⽤场景,主要有以下⼏种:

  1. 时间戳(timestamp),特定的时刻。
  2. 固定时期(period),如2007年1⽉或2010年全年。
  3. 时间间隔(interval),由起始和结束时间戳表示。时期(period)可以被看做间隔(interval)的特例。
  4. 实验或过程时间,每个时间点都是相对于特定起始时间的⼀个度量。例如,从放⼊烤箱时起,每秒钟饼⼲的直径。

下面主要讲解前3种时间序列。许多技术都可⽤于处理实验型时间序列,其索引可能是⼀个整数或浮点数(表示从实验开始算起已经过去的时间)。最简单也最常⻅的时间序列都是⽤时间戳进⾏索引的。

日期和时间数据类型及⼯具

import numpy as np
import pandas as pd
np.random.seed(12345)
import matplotlib.pyplot as plt
plt.rc('figure', figsize=(10, 6))
PREVIOUS_MAX_ROWS = pd.options.display.max_rows
pd.options.display.max_rows = 20
np.set_printoptions(precision=4, suppress=True)

Python标准库包含⽤于⽇期(date)和时间(time)数据的数据类型,⽽且还有⽇历⽅⾯的功能。我们主要会⽤到datetime、time以及calendar模块。datetime.datetime(也可以简写为datetime)是⽤得最多的数据类型:

from datetime import datetime
now = datetime.now()
now

在这里插入图片描述

now.year, now.month, now.day

在这里插入图片描述
datetime以毫秒形式存储⽇期和时间。timedelta表示两个datetime对象之间的时间差:

delta = datetime(2011, 1, 7) - datetime(2008, 6, 24, 8, 15)
delta

在这里插入图片描述

delta.days

在这里插入图片描述

delta.seconds

在这里插入图片描述
可以给datetime对象加上(或减去)⼀个或多个timedelta,这样会产⽣⼀个新对象:

from datetime import timedelta
start = datetime(2011, 1, 7)
start + timedelta(12)

在这里插入图片描述

start - 2 * timedelta(12)

在这里插入图片描述
datetime模块中的数据类型参⻅表1。虽然主要讲的是pandas数据类型和⾼级时间序列处理,但你肯定会在Python的其他地⽅遇到有关datetime的数据类型。
表1 datetime模块中的数据类型

类型 说明
date 以公历形式存储日历日期(年月日)
time 将时间存储为时,分,秒,毫秒
datetime 存储日期和时间
timedelta 表示两个datetime值之间的差(日,秒,毫秒)
tzinfo 存储时区信息的基本类型

字符串和datetime的相互转换

利⽤str或strftime⽅法(传⼊⼀个格式化字符串,datetime对象和pandas的Timestamp对象(稍后就会介绍) 可以被格式化为字符串

stamp = datetime(2011, 1, 3)
str(stamp)
stamp.strftime('%Y-%m-%d')

在这里插入图片描述
表2列出了全部的格式化编码。
表2 datetime格式定义(兼容ISO C89)

代码 说明
%Y 4位数的年
%y 2位数的年
%m 2位数的月
%d 2位数的日
%H 时(24小时制)
%I 时(12小时制)
%M 2位数的分
%S 秒[0,61](秒60和秒61用于闰秒)
%w 用于整数表示的星期几[0(星期天),6]
%U 每年的第几周【0,53】。星期天被认为是每周的第一天,每年第一个星期天之前的那几天被认为是第0周
%W 每年的第几周【0,53】。星期一被认为是每周的第一天,每年的第一个星期一之前的那几天会被认为是第0周
%z 以+HHMM或-HHMM表示的UTC时区偏移量,如果时区为naive,则返回空的字符串
%F %Y-%m-%d简写形式
%D %m%d%y简写形式

datetime.strptime可以⽤这些格式化编码将字符串转换为⽇期:

value = '2011-01-03'
datetime.strptime(value, '%Y-%m-%d')

datestrs = ['7/6/2011', '8/6/2011']
[datetime.strptime(x, '%m/%d/%Y') for x in datestrs]

在这里插入图片描述
datetime.strptime是通过已知格式进⾏⽇期解析的最佳⽅式。但是每次都要编写格式定义是很麻烦的事情,尤其是对于⼀些常⻅的⽇期格式。这种情况下,你可以⽤dateutil这个第三⽅包中的parser.parse⽅法(pandas中已经⾃动安装好了):

from dateutil.parser import parse
parse('2011-01-03')

在这里插入图片描述
parse可以解析⼏乎所有⼈类能够理解的⽇期表示形式:

parse('Jan 31, 1997 10:45 PM')

在这里插入图片描述
在国际通⽤的格式中,⽇出现在⽉的前⾯很普遍,传⼊dayfirst=True即可解决这个问题:

parse('6/12/2011', dayfirst=True)

在这里插入图片描述
pandas通常是⽤于处理成组⽇期的,不管这些⽇期是DataFrame的轴索引还是列。to_datetime⽅法可以解析多种不同的⽇期表示形式。对标准⽇期格式(如ISO8601)的解析⾮常快:

datestrs = ['2011-07-06 12:00:00', '2011-08-06 00:00:00']
pd.to_datetime(datestrs)

在这里插入图片描述
它还可以处理缺失值(None、空字符串等):

#处理缺失值
idx = pd.to_datetime(datestrs + [None])
idx

在这里插入图片描述

idx[2]

pd.isnull(idx)

在这里插入图片描述
NaT(Not a Time)是pandas中时间戳数据的null值。
注意:dateutil.parser是⼀个实⽤但不完美的⼯具。⽐如说,它会把⼀些原本不是⽇期的字符串认作是⽇期(⽐如"42"会被解析为2042年的今天)。
datetime对象还有⼀些特定于当前环境(位于不同国家或使⽤不同语⾔的系统)的格式化选项。例如,德语或法语系统所⽤的⽉份简写就与英语系统所⽤的不同。表3进⾏了总结。
表3 特定于当前环境的⽇期格式

代码 说明
%a 星期几的简写
%A 星期几的全称
%b 月份的简写
%B 月份的全称
%c 完整的日期和时间,例如“Tue01 May 2012 04:20:57 PM”
%p 不同环境中的AM或PM
%x 适合于当前环境的日期格式,例如在美国,“May 1 2012“会产生“05/01/2012”
%X 适合于当前环境的时间格式

时间序列基础

pandas最基本的时间序列类型就是以时间戳(通常以Python字符串或datatime对象表示)为索引的Series:

from datetime import datetime
dates = [datetime(2011, 1, 2), datetime(2011, 1, 5),
         datetime(2011, 1, 7), datetime(2011, 1, 8),
         datetime(2011, 1, 10), datetime(2011, 1, 12)]
ts = pd.Series(np.random.randn(6), index=dates)
ts

在这里插入图片描述
这些datetime对象实际上是被放在⼀个DatetimeIndex中的:

ts.index

在这里插入图片描述
跟其他Series⼀样,不同索引的时间序列之间的算术运算会⾃动按⽇期对⻬:

ts + ts[::2]

在这里插入图片描述
pandas⽤NumPy的datetime64数据类型以纳秒形式存储时间戳:

ts.index.dtype

在这里插入图片描述
DatetimeIndex中的各个标量值是pandas的Timestamp对象:

stamp = ts.index[0]
stamp

在这里插入图片描述
只要有需要,TimeStamp可以随时⾃动转换为datetime对象。此外,它还可以存储频率信息(如果有的话),且知道如何执⾏时区转换以及其他操作。稍后将对此进⾏详细讲解。

索引、选取、子集构造

当你根据标签索引选取数据时,时间序列和其它的pandas.Series很像:

stamp = ts.index[2]
ts[stamp]

在这里插入图片描述
还有⼀种更为⽅便的⽤法:传⼊⼀个可以被解释为⽇期的字符串:

ts['1/10/2011']
ts['20110110']

在这里插入图片描述
对于较⻓的时间序列,只需传⼊“年”或“年⽉”即可轻松选取数据的切⽚:

longer_ts = pd.Series(np.random.randn(1000),
                      index=pd.date_range('1/1/2000', periods=1000))
longer_ts

longer_ts['2001']

在这里插入图片描述
这⾥,字符串“2001”被解释成年,并根据它选取时间区间。指定⽉也同样奏效:

longer_ts['2001-05']

在这里插入图片描述
datetime对象也可以进⾏切⽚:

ts[datetime(2011, 1, 7):]

在这里插入图片描述
由于⼤部分时间序列数据都是按照时间先后排序的,因此你也可以⽤不存在于该时间序列中的时间戳对其进⾏切⽚(即范围查询):

ts

ts['1/6/2011':'1/11/2011']

在这里插入图片描述
跟之前⼀样,你可以传⼊字符串⽇期、datetime或Timestamp。注意,这样切⽚所产⽣的是源时间序列的视图,跟NumPy数组的切⽚运算是⼀样的。
这意味着,没有数据被复制,对切⽚进⾏修改会反映到原始数据上。
此外,还有⼀个等价的实例⽅法也可以截取两个⽇期之间TimeSeries:

ts.truncate(after='1/9/2011')

在这里插入图片描述
这些操作对DataFrame也有效。例如,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值