Python Pandas 时间序列处理:日期转换、索引与切片详解
本文深入解析 Python 中日期与时间数据的处理机制,涵盖 datetime 模块基础、字符串与日期互转方法及 Pandas 的 to_datetime 应用。重点讲解以时间戳为索引的 Series 和 DataFrame 的构建、算术对齐、高级切片技巧,以及针对重复时间索引数据的聚合处理方案,助力高效进行时间序列数据分析。
首先简要介绍日期和时间相关的数据类型及常用工具。
Python 标准库中内置了处理日期(date)和时间(time)的数据类型,其中 datetime、time 以及 calendar 模块在实际开发中使用频率较高。
datetime 对象以毫秒精度存储具体的日期和时间信息,而 timedelta 对象则用于表示两个 datetime 对象之间的时间差值。
对现有的 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 构造函数主要接受这三个核心参数。
以下是 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 |
最后进行总结。
本文主要涵盖以下内容:
第一,字符串与日期之间的转换方法。
第二,Python 中日期和时间的主要处理模块,包括 datetime、timedelta 以及 Pandas 的 to_datetime 等。
第三,以时间为索引的 Series 和 DataFrame 的索引操作与数据切片技巧。
第四,针对带有重复时间索引的情况,应用 .groupby(level=0) 进行数据处理。
以上关于 Python 结合 Pandas 处理时间、日期及时间序列的方法就是全部内容,希望能对大家有所帮助,欢迎支持。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













