使用datetime、zoneinfo、dateutil和pandas

最近我一直在处理时间序列数据,并在Python中处理日期和时间对象。为此,我学到了一些有用的技巧,可以简化我的代码中的复杂性。在本文中,我想分享并总结我学到的最有价值的技巧。
为了演示,我将使用两个Kaggle数据集,我会在使用它们时提供链接。如果你想跟着做,可以导入以下库。
Datetime、zoneinfo、dateutil和pytz
Python中常用的处理日期和时间的包有datetime、dateutil、pytz和最近的zoneinfo。Datetime是Python中用于处理日期和时间的内置模块,可以完成大部分基本操作。Dateutil和pytz是第三方模块,是对datetime的强大扩展,用于处理相对时间差、时区和字符串解析等更复杂的操作。
然而,自从Python版本3.9起,zoneinfo已经纳入了Python标准库中,因此在处理时区支持时被认为比其他第三方模块如dateutil或pytz更加“方便”。
因此,根据你所使用的Python版本,Python内置模块可能已经足够,不需要使用第三方模块(如dateutil和pytz)来处理不同的时区!
在本文的剩余部分,我将主要关注使用datetime处理日期和时间,但也会提及zoneinfo或dateutil的潜在选项。本文首先介绍单个datetime对象的处理,然后介绍使用numpy和pandas处理数组和数据框中的日期。
- 从头开始创建日期或时间
- 转换和解析字符串:strftime()、strptime()和dateutil
- numpy中的日期和时间 —— numPy的datetime64
- pandas中的日期和时间
- 从日期和时间中创建特征
1. 从头开始创建日期或时间
datetime包允许你轻松地从头开始创建日期和时间对象,例如可以用作过滤的阈值(尝试打印下面创建的对象及其类型以更好地理解它们的格式)。
此外,datetime还允许你创建日期和时间对象,这些对象引用今天或现在。
在这里要小心,因为datetime对象通常是“时区无关的”,不指定特定的时区,这可能在与国际同事合作时给你带来麻烦!
借助zoneinfo模块(自Python版本3.9起内置),可以使用astimezone()的tz参数设置时区。
2. 转换和解析字符串:strftime()、strptime()和dateutil
你可能会遇到这样的情况,想要将datetime对象显示为字符串,或者将字符串转换为datetime对象。在这里,strftime()和strptime()函数非常有用。
将datetime对象(或其部分)转换为字符串
常用的用于描述datetime对象的格式代码可以在此处找到。
将字符串转换为datetime对象
使用dateutil解析复杂字符串
3. numpy中的日期和时间 —— numPy的datetime64
如果你处理大型数据集,numpy的datetime64可能会很有用,因为由于其设计,它比使用datetime和dateutil对象更快。numpy中的datetime64数据类型将日期和时间编码为64位整数。
这可以紧凑地存储日期和时间,并允许对numpy数组的每个元素应用向量化操作。
从上面的代码运行结果可以看出,使用datetime或dateutil对象进行向量化操作会导致错误。
4. pandas中的日期和时间
在处理时间序列数据项目时,Pandas可以是一个不错的选择。
著名的数据处理库Pandas将datetime和dateutil的便利性与numpy的有效存储和操作功能相结合。
创建一个解析日期列的pandas数据帧(从CSV)
现在,我们对使用numpy和pandas处理Python中的日期和时间有了基本的了解。然而,通常情况下,我们不会自己创建日期和时间,而是已经包含在我们处理的数据集中。让我们创建一个带有日期列的pandas数据帧(Kaggle数据集NFL)。
如您所见,当从CSV加载时,如果没有明确指定,保存日期的列会被转换为字符串格式。要接收日期格式,您可以创建一个额外的列名为“gameDate_dateformat”,或者直接通过参数parse_dates在pd.read_csv()中传递日期列。
在处理时间序列数据时,另一个方便的操作是能够按日期/时间进行过滤或使用日期/时间对数据帧进行子集选择。有两种方法可以实现这一点:过滤/子集选择或索引。
按时间过滤pandas数据帧
确保用于子集选择的阈值日期与列的格式相同!
如果要过滤的列具有datetime格式(如示例中所示),则比较日期不能是日期,而是需要具有datetime格式!
按时间索引pandas数据帧
更强大的是按日期或时间对pandas数据帧进行索引。
在处理时间序列时,索引非常有用,因为有滚动窗口和时间偏移等方法。
5. 从日期和时间创建特征
通常,我们对日期本身不感兴趣,但可能对持续时间、工作日或日期时间的一部分(例如年份)感兴趣。为此,datetime和pandas都提供了一些有用的操作。
时间差
使用pandas,您可以计算两个日期时间之间的差异。为此,我们将查看一个不同的Uber行程数据集(Kaggle数据集Uber),其中包含开始和结束时间戳。需要进行一些预处理(删除Total行)才能开始研究时间差。
提取工作日或月份
对于单个datetime和pandas Series,这个操作略有不同。单个datetime对象的工作日或月份可以直接通过添加属性(例如.month)或方法(例如.weekday())来访问,而pandas Series始终需要使用.dt访问器。
dt.访问器允许您从datetime Series中访问特定于日期时间的属性和方法。
创建日期/时间滞后
对于时间序列数据,另一个有用的操作是添加一个额外的列,以添加日期或日期时间的滞后。
总结
要在Python中处理日期或时间对象,了解内置的datetime包的基本知识(例如date()或strftime()和strptime())是有益的。Zoneinfo是一个新的内置包(自版本3.9起),在处理不同时区时比第三方模块更方便。Dateutil是一个有价值的库,用于处理单个日期对象的更高级的日期和时间操作,例如解析复杂字符串。在处理数据帧、Series或数组中的日期和时间时,pandas结合了datetime、dateutil和numpy的优点,并作为一个方便的库。
来源
- Modern Python Standard Library — Cookbook by Alessandro Molina (2018)
- Python Data Science Handbook by Jake VanderPlas (2017)
- Datacamp课程:在Python中处理日期和时间(2022)
- https://dateutil.readthedocs.io/en/stable/
- https://docs.python.org/3/library/datetime.html
- https://docs.python.org/3/library/zoneinfo.html
- https://peps.python.org/pep-0615/
- https://github.com/stub42/pytz/blob/master/src/README.rst#issues–limitations