Python时间与日期处理:从datetime到pandas时间序列实战
本文详细介绍Python标准库中的日期时间数据类型,包括datetime、timedelta及calendar模块的使用。重点讲解字符串与datetime对象的相互转换方法,涵盖标准库函数、dateutil.parser及pandas.to_datetime。此外,深入解析pandas中基于时间戳索引的Series与DataFrame操作,包括算术运算对齐、索引选取、切片技巧以及处理重复索引时的聚合方法。
Python标准库内置了处理日期和时间数据的相关数据类型,其中datetime、time以及calendar模块是日常开发中最为常用的工具。
datetime对象以毫秒精度存储具体的日期和时间信息,而timedelta类则用于表示两个datetime对象之间的时间差值。
接下来,我们将简要介绍Python中涉及日期和时间的主要数据类型及相关工具。
对datetime对象执行加上或减去一个或多个timedelta的操作,将生成一个新的datetime对象。
from datetime import datetime from datetime import timedelta now = datetime.now() now datetime.datetime(2017, 6, 27, 15, 56, 56, 167000) datetime参数:datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]]) delta = now - datetime(2017,6,27,10,10,10,10) delta datetime.timedelta(0, 20806, 166990) delta.days 0 delta.seconds 20806 delta.microseconds 166990
datetime模块中定义的核心数据类型如下所示。
| 类型 | 说明 |
|---|---|
| date | 以公历形式存储日历日期(年、月、日) |
| time | 将时间存储为时、分、秒、毫秒 |
| datetime | 存储日期和时间 |
| timedelta | 表示两个datetime值之间的差(日、秒、毫秒) |
字符串格式与datetime对象之间的相互转换是常见需求。
首先介绍Python标准库提供的内置函数。
将日期转换为字符串时,可以使用str()函数或直接调用strftime()方法。
将字符串解析为日期对象,则需使用datetime.strptime()函数。
stamp = datetime(2017,6,27)
str(stamp)
'2017-06-27 00:00:00'
stamp.strftime('%y-%m-%d')#%Y是4位年,%y是2位年
'17-06-27'
#对多个时间进行解析成字符串
date = ['2017-6-26','2017-6-27']
datetime2 = [datetime.strptime(x,'%Y-%m-%d') for x in date]
datetime2
[datetime.datetime(2017, 6, 26, 0, 0), datetime.datetime(2017, 6, 27, 0, 0)]
其次,第三方库dateutil.parser提供了强大的时间解析功能。
from dateutil.parser import parse
parse('2017-6-27')
datetime.datetime(2017, 6, 27, 0, 0)
parse('27/6/2017',dayfirst =True)
datetime.datetime(2017, 6, 27, 0, 0)
最后,pandas库提供了处理成组日期数据的高效方法。
pandas广泛应用于处理成组日期数据,无论这些日期作为DataFrame的轴索引还是普通列,to_datetime()方法都能解析多种不同的日期表示格式。
date ['2017-6-26', '2017-6-27'] import pandas as pd pd.to_datetime(date) DatetimeIndex(['2017-06-26', '2017-06-27'], dtype='datetime64[ns]', freq=None)
以下是常用的datetime格式定义代码及其说明。
| 代码 | 说明 |
|---|---|
| %Y | 4位数的年 |
| %y | 2位数的年 |
| %m | 2位数的月[01,12] |
| %d | 2位数的日[01,31] |
| %H | 时(24小时制)[00,23] |
| %l | 时(12小时制)[01,12] |
| %M | 2位数的分[00,59] |
| %S | 秒[00,61]有闰秒的存在 |
| %w | 用整数表示的星期几[0(星期天),6] |
| %F | %Y-%m-%d简写形式例如,2017-06-27 |
| %D | %m/%d/%y简写形式 |
本节介绍pandas时间序列的基础知识及日期处理技巧。
pandas中最基本的时间序列类型,是索引为时间戳(通常以Python字符串或datetime对象表示)的Series。
dates = ['2017-06-20','2017-06-21',\
'2017-06-22','2017-06-23','2017-06-24','2017-06-25','2017-06-26','2017-06-27']
import numpy as np
ts = pd.Series(np.random.randn(8),index = pd.to_datetime(dates))
ts
2017-06-20 0.788811
2017-06-21 0.372555
2017-06-22 0.009967
2017-06-23 -1.024626
2017-06-24 0.981214
2017-06-25 0.314127
2017-06-26 -0.127258
2017-06-27 1.919773
dtype: float64
ts.index
DatetimeIndex(['2017-06-20', '2017-06-21', '2017-06-22', '2017-06-23',
'2017-06-24', '2017-06-25', '2017-06-26', '2017-06-27'],
dtype='datetime64[ns]', freq=None)
当对不同索引的时间序列进行算术运算时,pandas会自动按照日期进行对齐。
ts[::2]#从前往后每隔两个取数据 2017-06-20 0.788811 2017-06-22 0.009967 2017-06-24 0.981214 2017-06-26 -0.127258 dtype: float64 ts[::-2]#从后往前逆序每隔两个取数据 2017-06-27 1.919773 2017-06-25 0.314127 2017-06-23 -1.024626 2017-06-21 0.372555 dtype: float64 ts + ts[::2]#自动数据对齐 2017-06-20 1.577621 2017-06-21 NaN 2017-06-22 0.019935 2017-06-23 NaN 2017-06-24 1.962429 2017-06-25 NaN 2017-06-26 -0.254516 2017-06-27 NaN dtype: float64
本节讨论索引为日期的Series和DataFrame数据的索引选取、切片及子集构建方法。
方法一:通过.index[number_int]直接访问索引元素。
方法二:使用一个可以被解析为日期的字符串作为键进行访问。
方法三:对于较长的时间序列,仅传入‘年'或‘年月'字符串,即可返回对应时间段的数据切片。
方法四:通过指定时间范围进行切片索引,获取区间内的数据。
ts 2017-06-20 0.788811 2017-06-21 0.372555 2017-06-22 0.009967 2017-06-23 -1.024626 2017-06-24 0.981214 2017-06-25 0.314127 2017-06-26 -0.127258 2017-06-27 1.919773 dtype: float64 ts[ts.index[2]] 0.0099673896063391908 ts['2017-06-21']#传入可以被解析成日期的字符串 0.37255538918121028 ts['21/06/2017'] 0.37255538918121028 ts['20170621'] 0.37255538918121028 ts['2017-06']#传入年或年月 2017-06-20 0.788811 2017-06-21 0.372555 2017-06-22 0.009967 2017-06-23 -1.024626 2017-06-24 0.981214 2017-06-25 0.314127 2017-06-26 -0.127258 2017-06-27 1.919773 dtype: float64 ts['2017-06-20':'2017-06-23']#时间范围进行切片 2017-06-20 0.788811 2017-06-21 0.372555 2017-06-22 0.009967 2017-06-23 -1.024626 dtype: float64
本节探讨带有重复索引的时间序列处理方法。
首先,利用.index.is_unique属性检查索引日期是否唯一。
其次,对非唯一时间戳的数据进行聚合时,可通过groupby()方法并传入level=0(指定索引的唯一层级)来实现。
dates = pd.DatetimeIndex(['2017/06/01','2017/06/02','2017/06/02','2017/06/02','2017/06/03'])
dates
DatetimeIndex(['2017-06-01', '2017-06-02', '2017-06-02', '2017-06-02',
'2017-06-03'],
dtype='datetime64[ns]', freq=None)
dup_ts = pd.Series(np.arange(5),index = dates)
dup_ts
2017-06-01 0
2017-06-02 1
2017-06-02 2
2017-06-02 3
2017-06-03 4
dtype: int32
dup_ts.index.is_unique
False
dup_ts['2017-06-02']
2017-06-02 1
2017-06-02 2
2017-06-02 3
dtype: int32
grouped = dup_ts.groupby(level=0).mean()
grouped
2017-06-01 0
2017-06-02 2
2017-06-03 4
dtype: int32
dup_df = pd.DataFrame(np.arange(10).reshape((5,2)),index = dates )
dup_df
| 0 | 1 | |
|---|---|---|
| 2017-06-01 | 0 | 1 |
| 2017-06-02 | 2 | 3 |
| 2017-06-02 | 4 | 5 |
| 2017-06-02 | 6 | 7 |
| 2017-06-03 | 8 | 9 |
grouped_df = dup_df.groupby(level=0).mean()##针对DataFrame grouped_df
| 0 | 1 | |
|---|---|---|
| 2017-06-01 | 0 | 1 |
| 2017-06-02 | 4 | 5 |
| 2017-06-03 | 8 | 9 |
本文主要总结了以下4个关键知识点。
第一,字符串与日期之间的转换方法。
第二,Python中处理日期和时间的主要类,包括datetime、timedelta以及pandas.to_datetime()等。
第三,以时间为索引的Series和DataFrame的索引选取与切片操作。
第四,处理带有重复时间索引时的索引技巧,特别是.groupby(level=0)的应用场景。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













