如何轻松处理时间序列数据
来源:Pandas官网:https://pandas.pydata.org/docs/getting_started/intro_tutorials/index.html
笔记托管:https://gitee.com/DingJiaxiong/machine-learning-study
文章目录
- 如何轻松处理时间序列数据
- 导包
- 数据准备
- 【1】使用Pandas日期时间属性
- 【2】日期时间作为索引
- 【3】将时间序列重新采样为另一个频率
- 【小结】
导包
import pandas as pd
import matplotlib.pyplot as plt
数据准备
air_quality_no2_long.csv"数据集提供 N O 2 NO_2 NO2 分别位于巴黎、安特卫普和伦敦的 FR04014、BETR801 和伦敦威斯敏斯特测量站的值。
air_quality = pd.read_csv("air_quality_no2_long.csv")
air_quality = air_quality.rename(columns={"date.utc": "datetime"})
air_quality.head()
city | country | datetime | location | parameter | value | unit | |
---|---|---|---|---|---|---|---|
0 | Paris | FR | 2019-06-21 00:00:00+00:00 | FR04014 | no2 | 20.0 | µg/m³ |
1 | Paris | FR | 2019-06-20 23:00:00+00:00 | FR04014 | no2 | 21.8 | µg/m³ |
2 | Paris | FR | 2019-06-20 22:00:00+00:00 | FR04014 | no2 | 26.5 | µg/m³ |
3 | Paris | FR | 2019-06-20 21:00:00+00:00 | FR04014 | no2 | 24.9 | µg/m³ |
4 | Paris | FR | 2019-06-20 20:00:00+00:00 | FR04014 | no2 | 21.4 | µg/m³ |
air_quality.city.unique()
array(['Paris', 'Antwerpen', 'London'], dtype=object)
【1】使用Pandas日期时间属性
我想将日期时间列中的日期用作datetime对象而不是纯文本
air_quality["datetime"] = pd.to_datetime(air_quality["datetime"])
air_quality["datetime"]
0 2019-06-21 00:00:00+00:00
1 2019-06-20 23:00:00+00:00
2 2019-06-20 22:00:00+00:00
3 2019-06-20 21:00:00+00:00
4 2019-06-20 20:00:00+00:00
...
2063 2019-05-07 06:00:00+00:00
2064 2019-05-07 04:00:00+00:00
2065 2019-05-07 03:00:00+00:00
2066 2019-05-07 02:00:00+00:00
2067 2019-05-07 01:00:00+00:00
Name: datetime, Length: 2068, dtype: datetime64[ns, UTC]
最初,datetime 中的值是字符串,不提供任何日期时间操作(例如,提取年份、星期几,…)。通过应用 to_datetime 函数,pandas 解释字符串并将其转换为日期时间(即 datetime64[ns, UTC])对象。在 pandas 中,我们将这些类似于标准库中datetime.datetime 对象称为 pandas.Timestamp.
由于许多数据集在其中一列中包含日期时间信息,因此 pandas.read_csv() 和 pandas.read_json() 等 pandas 输入函数可以在使用 parse_dates 参数读取数据时转换为日期,并列出要读取为 Timestamp 的列表:
pd.read_csv("…/data/air_quality_no2_long.csv", parse_dates=[“datetime”])
为什么这些pandas.Timestamp对象有用吗?【举些栗子】
我们正在处理的时间序列数据集的开始和结束日期是什么?
air_quality["datetime"].min(), air_quality["datetime"].max()
(Timestamp('2019-05-07 01:00:00+0000', tz='UTC'),
Timestamp('2019-06-21 00:00:00+0000', tz='UTC'))
使用pandas.Timestamp日期时间的时间戳使我们能够使用日期信息进行计算并使它们具有可比性。因此,我们可以使用它来获取时间序列的长度:
air_quality["datetime"].max() - air_quality["datetime"].min()
Timedelta('44 days 23:00:00')
结果是一个 pandas.Timedelta 对象,类似于标准 Python 库中的 datetime.timedelta,并定义了持续时间。
我想向DataFrame添加一个仅包含测量月份的新列
air_quality["month"] = air_quality["datetime"].dt.month
air_quality.head()
city | country | datetime | location | parameter | value | unit | month | |
---|---|---|---|---|---|---|---|---|
0 | Paris | FR | 2019-06-21 00:00:00+00:00 | FR04014 | no2 | 20.0 | µg/m³ | 6 |
1 | Paris | FR | 2019-06-20 23:00:00+00:00 | FR04014 | no2 | 21.8 | µg/m³ | 6 |
2 | Paris | FR | 2019-06-20 22:00:00+00:00 | FR04014 | no2 | 26.5 | µg/m³ | 6 |
3 | Paris | FR | 2019-06-20 21:00:00+00:00 | FR04014 | no2 | 24.9 | µg/m³ | 6 |
4 | Paris | FR | 2019-06-20 20:00:00+00:00 | FR04014 | no2 | 21.4 | µg/m³ | 6 |
通过使用日期的Timestamp对象,pandas提供了许多与时间相关的属性。例如month,还有year、weekofyear、quarter,…所有这些属性都可以由 dt 访问器访问。
什么是平均值 N O 2 NO_2 NO2 每个测量位置一周中每天的浓度?
air_quality.groupby([air_quality["datetime"].dt.weekday, "location"])["value"].mean()
datetime location
0 BETR801 27.875000
FR04014 24.856250
London Westminster 23.969697
1 BETR801 22.214286
FR04014 30.999359
London Westminster 24.885714
2 BETR801 21.125000
FR04014 29.165753
London Westminster 23.460432
3 BETR801 27.500000
FR04014 28.600690
London Westminster 24.780142
4 BETR801 28.400000
FR04014 31.617986
London Westminster 26.446809
5 BETR801 33.500000
FR04014 25.266154
London Westminster 24.977612
6 BETR801 21.896552
FR04014 23.274306
London Westminster 24.859155
Name: value, dtype: float64
还记得 groupby 在统计计算教程中提供的拆分-应用-组合模式吗?在这里,我们要计算一个给定的统计量(例如平均值 N O 2 NO_2 NO2 ) 对于每个工作日和每个测量位置。为了在工作日分组,我们使用 pandas Timestamp的日期时间属性weekday(星期一=0 和星期日=6),dt 访问器也可以访问该属性。可以对位置和工作日进行分组,以拆分每个组合的均值计算。
绘制典型 N O 2 NO_2 NO2 我们所有站的时间序列中的模式。换句话说,一天中每个小时的平均值是多少?
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")
plt.ylabel("$NO_2 (µg/m^3)$")
Text(0, 0.5, '$NO_2 (µg/m^3)$')
与前一种情况类似,我们想要计算给定的统计量(例如平均值 N O 2 NO_2 NO2 ) 对于一天中的每一个小时,我们可以再次使用拆分-应用-组合方法。对于这种情况,我们使用 pandas Timestamp的日期时间属性 hour,它也可以通过 dt 访问器访问。
【2】日期时间作为索引
引入 pivot() 来重塑数据表,并将每个测量位置作为单独的列
no_2 = air_quality.pivot(index="datetime", columns="location", values="value")
no_2.head()
location | BETR801 | FR04014 | London Westminster |
---|---|---|---|
datetime | |||
2019-05-07 01:00:00+00:00 | 50.5 | 25.0 | 23.0 |
2019-05-07 02:00:00+00:00 | 45.0 | 27.7 | 19.0 |
2019-05-07 03:00:00+00:00 | NaN | 50.4 | 19.0 |
2019-05-07 04:00:00+00:00 | NaN | 61.9 | 16.0 |
2019-05-07 05:00:00+00:00 | NaN | 72.4 | NaN |
通过透视数据,日期时间信息成为表的索引。通常,可以通过set_index函数将列设置为索引。
使用日期时间索引(即DatetimeIndex)提供了强大的功能。例如,我们不需要 dt 访问器来获取时间序列属性,而是直接在索引上提供这些属性:
no_2.index.year, no_2.index.weekday
(Int64Index([2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019,
...
2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019],
dtype='int64', name='datetime', length=1033),
Int64Index([1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
...
3, 3, 3, 3, 3, 3, 3, 3, 3, 4],
dtype='int64', name='datetime', length=1033))
其他一些优点是方便的时间段子集或图上适应的时间尺度。
创建 N O 2 NO_2 NO2 从5月20日到5月21日结束的不同站的值
no_2["2019-05-20":"2019-05-21"].plot()
<AxesSubplot:xlabel='datetime'>
通过提供解析为日期时间的字符串,可以在 DatetimeIndex 上选择数据的特定子集.
【3】将时间序列重新采样为另一个频率
将当前每小时时间序列值聚合为每个站点中的每月最大值。
monthly_max = no_2.resample("M").max()
monthly_max
location | BETR801 | FR04014 | London Westminster |
---|---|---|---|
datetime | |||
2019-05-31 00:00:00+00:00 | 74.5 | 97.0 | 97.0 |
2019-06-30 00:00:00+00:00 | 52.5 | 84.7 | 52.0 |
使用日期时间索引的时间序列数据的一个非常强大的方法是能够resample()另一个频率(例如,将次要数据转换为 5 分钟数据)。
resample() 方法类似于 groupby 操作:
- 它通过使用定义目标频率的字符串(例如 M、5H,…)提供基于时间的分组
- 它需要一个聚合函数,例如mean、max,…
定义后,时间序列的频率由 freq 属性提供:
monthly_max.index.freq
<MonthEnd>
绘制每日平均值图 N O 2 NO_2 NO2 每个站的价值。
no_2.resample("D").mean().plot(style="-o", figsize=(10, 5))
<AxesSubplot:xlabel='datetime'>
【小结】
可以使用to_datetime函数或作为读取函数的一部分将有效的日期字符串转换为日期时间对象。
pandas 中的日期时间对象支持使用 dt 访问器的计算、逻辑运算和方便的日期相关属性。
日期DatetimeIndex包含这些与日期相关的属性,并支持方便的切片。
Resample是更改时间序列频率的强大方法。