Pandas时间序列数据处理
1.好用的Python库
Python很强大,有很多的好用的库:
2.Pandas历史
本文主要介绍Pandas库,Pandas在数据科学中十分常用,Pandas的位置如下:
Pandas诞生于2008年,它的开发者是Wes McKinney,一个量化金融分析工程师。因为疲于应付繁杂的财务数据,Wes McKinney便自学Python,并开发了Pandas。
2009年底,开源,今天得到了来自世界各地志同道合的个人社区的积极支持。
自2015年以来,pandas是NumFOCUS赞助的项目。
为什么叫作Pandas,其实这是“Python data analysis”的简写,同时也衍生自计量经济学术语“panel data”(面板数据)。
3.时序数据处理
Pandas可以处理很多的数据类型,其中最初始也最有趣的数据类型之一就是时间序列数据。Pandas 基本上是为分析金融时间序列数据而开发的,并为处理时间、日期和时间序列数据提供了一整套全面的框架。时间序列数据在很对行业都有应用,如股票价格变化、天气记录、患者健康指标、和应用程序性能监控等。
3.1 时序中的基本对象
时间序列的概念在日常生活中十分常见,但对于一个具体的时序事件而言,可以从多个时间对象的角度来描述。例如2020年9月7日周一早上8点整需要到教室上课,这个课会在当天早上10点结束,其中包含了哪些时间概念?
第一,会出现时间戳(Date times)的概念,即'2020-9-7 08:00:00'和'2020-9-7 10:00:00'这两个时间点分别代表了上课和下课的时刻,在pandas中称为Timestamp。同时,一系列的时间戳可以组成DatetimeIndex,而将它放到Series中后,Series的类型就变为了datetime64[ns],如果有涉及时区则为datetime64[ns, tz],其中tz是timezone的简写。
第二,会出现时间差(Time deltas)的概念,即上课需要的时间,两个Timestamp做差就得到了时间差,pandas中利用Timedelta来表示。类似的,一系列的时间差就组成了TimedeltaIndex, 而将它放到Series中后,Series的类型就变为了timedelta64[ns]。
第三,会出现时间段(Time spans)的概念,即在8点到10点这个区间都会持续地在上课,在pandas利用Period来表示。类似的,一系列的时间段就组成了PeriodIndex, 而将它放到Series中后,Series的类型就变为了Period。
第四,会出现日期偏置(Date offsets)的概念,假设你只知道9月的第一个周一早上8点要去上课,但不知道具体的日期,那么就需要一个类型来处理此类需求。再例如,想要知道2020年9月7日后的第30个工作日是哪一天,那么时间差就解决不了你的问题,从而pandas中的DateOffset就出现了。同时,pandas中没有为一列时间偏置专门设计存储类型,理由也很简单,因为需求比较奇怪,一般来说我们只需要对一批时间特征做一个统一的特殊日期偏置。
通过这个简单的例子,就能够容易地总结出官方文档中的这个表格:
概念 | 单元素类型 | 数组类型 | pandas数据类型 |
Date times | Timestamp |
DatetimeIndex |
datetime64[ns] |
Time deltas | Timedelta |
TimedeltaIndex |
timedelta64[ns] |
Time spans | Period |
PeriodIndex |
period[freq] |
Date offsets | DateOffset |
None |
None |
由于时间段对象Period/PeriodIndex
的使用频率并不高,因此将不进行讲解,而只涉及时间戳序列、时间差序列和日期偏置的相关内容。
我们可以将时间序列数据定义为在不同时间间隔获得并按时间顺序排列的数据点的集合
3.2 python中的datetime模块
datetime模块,主要掌握:datetime.date(), datetime.datetime(), datetime.timedelta()
日期解析方法:parser.parse
1. date对象:
# datetime.date:date对象 import datetime # 也可以写 from datetime import date today = datetime.date.today() print(today,type(today)) # datetime.date.today 返回今日 # 输出格式为 date类 (年,月,日) → 直接得到当时日期 t = datetime.date(2022,10,1) print(t)
输出为:
2022-10-21 <class 'datetime.date'> 2022-10-01
2. datetime对象
# datetime.datetime:datetime对象 now = datetime.datetime.now() print(now,type(now)) # .now()方法,输出当前时间 # 输出格式为 datetime类 # 可通过str()转化为字符串 t1 = datetime.datetime(2022,10,1) t2 = datetime.datetime(2022,10,1,1,0,0) print(t1,t2) # (年,月,日,时,分,秒),至少输入年月日 print("*"*10) print(t2-t1) t2-t1 # 输出为 datetime.timedelta(0, 3600) # 相减得到时间差 —— timedelta
输出为:
2022-10-21 19:43:08.461654 <class 'datetime.datetime'> 2022-10-01 00:00:00 2022-10-01 01:00:00 ********** 1:00:00 datetime.timedelta(0, 3600)
3. datetime.timedelta:时间差
# datetime.timedelta:时间差 today = datetime.datetime.today() # datetime.datetime也有today()方法 yestoday = today - datetime.timedelta(1) # print(today) print(yestoday) print(today - datetime.timedelta(7)) # 时间差主要用作时间的加减法,相当于可被识别的时间“差值”
输出为:
2022-10-21 19:44:23.097770 2022-10-20 19:44:23.097770 2022-10-14 19:44:23.097770
4. parser.parse:日期字符串转换
# parser.parse:日期字符串转换 from dateutil.parser import parse date = '10-01-2022' t = parse(date) print(t,type(t)) # 直接将str转化成datetime.datetime print(parse('2022-10-1'),'\n', parse('10/2/2021'),'\n', parse('10/3/2022', dayfirst = True),'\n', # 国际通用格式中,日在月之前,可以通过dayfirst来设置 parse('10/4/2022'),'\n', parse('Jan 31, 2022 10:45 PM')) # 各种格式可以解析,但无法支持中文
输出为:
2022-10-01 00:00:00 <class 'datetime.datetime'> 2022-10-01 00:00:00 2021-10-02 00:00:00 2022-03-10 00:00:00 2022-10-04 00:00:00 2022-01-31 22:45:00
3.3. 时间戳(Date times)的构造与属性
概念 | 单元素类型 | 数组类型 | pandas数据类型 |
Date times | Timestamp |
DatetimeIndex |
datetime64[ns] |
Time deltas | Timedelta |
TimedeltaIndex |
timedelta64[ns] |
Time spans | Period |
PeriodIndex |
period[freq] |
Date offsets | DateOffset |
None |
None |
1.Timestamp对象
单个时间戳的生成利用pd.Timestamp实现,一般而言的常见日期格式都能被成功地转换:
创建时间戳:
import datetime import numpy as np import pandas as pd date1 = datetime.datetime(2020,1,2,3,4,5) # 创建一个datetime.datetime date2 = '2020-1-2 03:04:05' # ts = pd.Timestamp(date1) # 这几种效果一样 # ts = pd.Timestamp(date2) # 这几种效果一样 ts = pd.Timestamp('2020-1-2 03:04:05') # 这几种效果一样 ts
输出为:
Timestamp('2020-01-02 03:04:05')
通过year, month, day, hour, min, second可以获取具体的数值:
# 通过year, month, day, hour, min, second可以获取具体的数值: print("*"*10) print(ts.year) print("*"*10) print(ts.month) print("*"*10) print(ts.day) print("*"*10) print(ts.hour) print("*"*10) print(ts.minute) print("*"*10) print(ts.second)
输出为:
********** 2020 ********** 1 ********** 2 ********** 3 ********** 4 ********** 5
在pandas
中,时间戳的最小精度为纳秒ns
,由于使用了64位存储,可以表示的时间范围大约可以如下计算:
通过pd.Timestamp.max
和pd.Timestamp.min
可以获取时间戳表示的范围,可以看到确实表示的区间年数大小正如上述计算结果:
print(pd.Timestamp.max) # Timestamp('2262-04-11 23:47:16.854775807') print(pd.Timestamp.min) # Timestamp('1677-09-21 00:12:43.145225') pd.Timestamp.max.year - pd.Timestamp.min.year # 585
输出为:
2 Datetime序列的生成
一组时间戳可以组成时间序列,可以用to_datetime和date_range来生成。其中,to_datetime能够把一列时间戳格式的对象转换成为datetime64[ns]类型的时间序列.
datetime64[ns]本质上可以理解为一个大整数,对于一个该类型的序列,可以使用max, min, mean,来取得最大时间戳、最小时间戳和“平均”时间戳
下面先对to_datetime方法进行演示:
1. to_datetime方法
单个时间数据,生成Timestamp:
# pd.to_datetime from datetime import datetime # pd.to_datetime():如果是单个时间数据,转换成pandas的时刻数据,数据类型为Timestamp date1 = datetime(2020,1,2,3,4,5) t1 = pd.to_datetime(date1) print(t1,type(t1)) t1 # 2020-01-02 03:04:05 <class 'pandas._libs.tslibs.timestamps.Timestamp'> # Timestamp('2020-01-02 03:04:05')
输出为:
多个时间数据生成DatetimeIndex:
lst_date = [ '2020-12-21', '2020-12-22', '2020-12-23'] t3 = pd.to_datetime(lst_date) print(t3,type(t3)) t3 # DatetimeIndex(['2020-12-21', '2020-12-22', '2020-12-23'], dtype='datetime64[ns]', freq=None) <class 'pandas.core.indexes.datetimes.DatetimeIndex'> # 多个时间数据,将会转换为pandas的DatetimeIndex
输出为:
时间戳格式转换
在极少数情况,时间戳的格式不满足转换时,可以强制使用format进行匹配:
temp = pd.to_datetime(['2020\\1\\1','2020\\1\\3'],format='%Y\\%m\\%d') temp # DatetimeIndex(['2020-01-01', '2020-01-03'], dtype='datetime64[ns]', freq=None)
输出为:
传入列表和series的返回值:
注意上面由于传入的是列表,而非pandas内部的Series,因此返回的是DatetimeIndex,如果想要转为datetime64[ns]的序列,需要显式用Series转化:
# DatetimeIndex # DatetimeIndex(['2020-01-01', '2020-01-03'], dtype='datetime64[ns]', freq=None) temp = pd.to_datetime(['2020\\1\\1','2020\\1\\3'],format='%Y\\%m\\%d') print(temp) # datetime64[ns]序列 pd.Series(temp).head()
输出为: