Pandas 时间序列入门实战:从 datetime 转换、dt 访问器到重采样
【免费下载链接】pandasFlexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more项目地址: https://gitcode.com/gh_mirrors/pa/pandas
引言
本教程来自 pandas 官方入门系列的第 9 篇(doc/source/getting_started/intro_tutorials/09_timeseries.rst),以真实的空气质量监测数据(NO₂ 与 PM2.5)为主线,系统讲解 pandas 时间序列处理的三块核心能力:把文本日期转换为 datetime 对象并使用 dt 访问器提取时间属性、以 DatetimeIndex 作为索引进行切片与绘图、以及通过 resample 改变时间序列频率。读完本文,你将能独立完成"数据清洗 → 时间特征提取 → 按时间分组统计 → 频率重采样"的完整实战链路。
本文使用的数据为NO_2和 PM2.5 空气质量数据,来自 OpenAQ 平台并经 py-openaq 包下载。其中 air_quality_no2_long.csv 记录了巴黎(FR04014)、安特卫普(BETR801)、伦敦(London Westminster)三个测量站点的 NO₂ 小时浓度值(字段:city, country, date.utc, location, parameter, value, unit)。
准备工作:加载并理解数据
本教程的数据存储在仓库的 doc/data/air_quality_no2_long.csv 中。首先读取数据并做两件基础处理:将date.utc列重命名为datetime(便于语义理解),并查看数据概貌:
import pandas as pd import matplotlib.pyplot as plt air_quality = pd.read_csv("data/air_quality_no2_long.csv") air_quality = air_quality.rename(columns={"date.utc": "datetime"}) air_quality.head()此时datetime列仍是纯文本字符串,尚不能进行提取年份、星期几等任何时间运算。我们还可以确认数据覆盖的站点:
air_quality.city.unique()使用 pandas datetime 属性
将文本日期转换为 Timestamp 对象
通过pd.to_datetime函数,pandas 会解析字符串并将其转换为 datetime 对象(示例中的时区格式解析结果为datetime64[us, UTC])。在 pandas 中,这类与标准库datetime.datetime相似的对象被称为pandas.Timestamp:
air_quality["datetime"] = pd.to_datetime(air_quality["datetime"]) air_quality["datetime"]从源码看,to_datetime是pandas中一个带多重重载的转换入口(pandas/core/tools/datetimes.py),它支持标量、Series、列表/元组/Index/类数组等多种输入形态,并暴露了丰富的参数:
| 参数 | 默认值 | 作用 |
|---|---|---|
errors | "raise" | 解析失败时的行为,可选"raise"、"coerce"(转为NaT)、"ignore" |
dayfirst/yearfirst | False | 控制日期中日月年的解析顺序 |
utc | False | 是否按 UTC 时区返回 |
format | None | 指定 strftime 格式模板,可大幅加速解析 |
unit | None | 数值输入的时间单位(如"s"、"ms"、"ns") |
origin | "unix" | 数值时间戳的参考原点 |
cache | True | 是否缓存唯一值以加速重复解析 |
提示:读文件时直接转换。很多数据集都含有日期列,pandas 的输入函数(如pd.read_csv、pd.read_json)支持通过parse_dates参数在读取阶段就把指定列转换为Timestamp,无需事后二次处理:
pd.read_csv("data/air_quality_no2_long.csv", parse_dates=["datetime"])Timestamp 带来的计算能力
为什么Timestamp对象有价值?因为它让日期信息可计算、可比较。例如获取时间序列的起止时间:
air_quality["datetime"].min(), air_quality["datetime"].max()进一步可以算出整个时间序列的时间跨度。相减的结果是一个pandas.Timedelta对象——类似于标准库的datetime.timedelta,用于表示时间持续长度:
air_quality["datetime"].max() - air_quality["datetime"].min()pandas 支持的各类时间概念(时间点、时间间隔、周期等)在用户指南的 time related concepts 章节中有系统介绍。
用 dt 访问器提取时间属性
基于Timestamp对象,pandas 提供了大量时间相关属性(如month、year、quarter等),全部通过dt访问器获取。例如新增一列仅含测量月份:
air_quality["month"] = air_quality["datetime"].dt.month air_quality.head()dt访问器在源码中的实现类是CombinedDatetimelikeProperties(pandas/core/indexes/accessors.py),它组合了DatetimeProperties、TimedeltaProperties与PeriodProperties三个能力集合,因此同一个访问器既能服务 datetime64 数据,也能服务 timedelta64 与 period 数据。可用的时间/日期组件属性完整对照表见用户指南的 time and date components 章节,dt访问器的更多细节见入门教程的 dt accessor 小节对应扩展(basics.dt_accessors)。
按星期与站点分组求均值(split-apply-combine)
沿用入门系列第 6 篇(06_calculate_statistics.rst)讲过的 split-apply-combine 模式:要计算每个星期几 × 每个站点的 NO₂ 平均浓度,只需用datetime属性的day_of_week(Monday=0,Sunday=6,同样经dt访问器取用)与location一起作为分组键:
air_quality.groupby( [air_quality["datetime"].dt.day_of_week, "location"])["value"].mean()由于本教程使用的时间序列非常短,上述分析结果**不具备长期代表性**,仅用于演示方法。绘制一天中的小时浓度模式
类似地,计算每个小时的平均 NO₂ 并绘制柱状图,即可观察所有站点共同的一天内污染变化规律:
fig, axs = plt.subplots(figsize=(12, 4)) air_quality.groupby(air_quality["datetime"].dt.hour)["value"].mean().plot( kind='bar', rot=0, ax=axs ) plt.xlabel("Hour of the day"); # custom x label using Matplotlib plt.ylabel("$NO_2 (µg/m^3)$");这里再次用到dt.hour属性,配合groupby实现按小时的聚合。
Datetime 作为索引
入门系列第 7 篇(07_reshape_table_layout.rst)介绍了pivot:把每个测量站点变成独立的一列,从而将表格重塑:
no_2 = air_quality.pivot(index="datetime", columns="location", values="value") no_2.head()透视之后,datetime 信息自动成为了表格的索引。一般而言,把某一列设为索引可以用 `set_index` 函数完成。拥有 datetime 索引(即DatetimeIndex)后,可以解锁强大的功能:不再需要dt访问器,时间属性直接挂在索引上:
no_2.index.year, no_2.index.day_of_weekDatetimeIndex在源码中定义为"不可变的 ndarray-like datetime64 数据"(pandas/core/indexes/datetimes.py),内部以 int64 存储、可装箱为携带元数据的Timestamp对象。其优势还包括便捷的时间段子集选取,以及自适应的绘图时间刻度。
用字符串切片选取时间段
例如绘制 5 月 20 日至 5 月 21 日各站点的 NO₂ 变化:直接传入可解析为 datetime 的字符串即可对DatetimeIndex完成子集选取:
no_2["2019-05-20":"2019-05-21"].plot();DatetimeIndex与字符串切片索引的更多细节见用户指南的 time series indexing 章节。
将时间序列重采样到其他频率
resample:按目标频率聚合
resample是处理带 datetime 索引时间序列时非常强大的方法,例如把小时级数据聚合为每个站点的月度最大值:
monthly_max = no_2.resample("MS").max() monthly_maxresample的用法与groupby类似:
- 它通过一个字符串(如
"M"、"5H"等)定义目标频率,进行基于时间的分组; - 它需要一个聚合函数(如
mean、max等)。
在源码中,resample返回的Resampler类被定义为"用于重采样 datetimelike 数据的、类似 groupby 的操作"(pandas/core/resample.py),支持aggregate、transform、apply等方法——这正是它和groupby在用法上高度一致的原因。
重采样后,时间序列的频率会记录在freq属性上:
monthly_max.index.freq频率别名(offset alias)的完整对照表见用户指南的 offset aliases 章节。
重采样 + 绘图:日平均 NO₂
再比如绘制每个站点的日均NO₂ 值,用"D"作为目标频率、mean作为聚合函数,并直接绘图:
no_2.resample("D").mean().plot(style="-o", figsize=(10, 5));重采样的更多高级能力(自定义聚合、asfreq、ohlc等)见用户指南的 resampling 章节。
核心要点回顾
- 有效日期字符串可通过
to_datetime函数转换,也可以在read_csv、read_json等读取函数中通过parse_dates参数一次性完成; - pandas 中的 datetime 对象支持计算、逻辑运算,并可借助
dt访问器获取各种日期相关属性; DatetimeIndex内建了这些日期相关属性,并支持便捷的字符串切片选取;resample是改变时间序列频率的强大方法,行为类似groupby。
关于时间序列的完整全景(时间点、间隔、周期、时区、频率转换等),参见用户指南的时间序列与日期功能章节。
【免费下载链接】pandasFlexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more项目地址: https://gitcode.com/gh_mirrors/pa/pandas
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考