In [1]: import pandas as pd
In [2]: import matplotlib.pyplot as plt
-
Air quality data
在本教程中,空气质量数据关于 \(NO_2\) 使用小于2.5微米的颗粒物,由 OpenAQ 并使用 py-openaq 包裹。这个
To raw dataair_quality_no2_long.csv"
数据集提供 \(NO_2\) 测量站的值 FR04014 , BETR801 和 伦敦威斯敏斯特 分别在巴黎、安特卫普和伦敦。In [3]: air_quality = pd.read_csv("data/air_quality_no2_long.csv") In [4]: air_quality = air_quality.rename(columns={"date.utc": "datetime"}) In [5]: air_quality.head() Out[5]: 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³
In [6]: air_quality.city.unique() Out[6]: array(['Paris', 'Antwerpen', 'London'], dtype=object)
如何轻松处理时间序列数据?#
使用Pandas日期时间属性#
我想使用列中的日期
datetime
作为DateTime对象,而不是纯文本In [7]: air_quality["datetime"] = pd.to_datetime(air_quality["datetime"]) In [8]: air_quality["datetime"] Out[8]: 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.datetime
来自标准库的pandas.Timestamp
。
备注
由于许多数据集在其中一列中确实包含DATETIME信息,因此PANDA输入函数如下 pandas.read_csv()
和 pandas.read_json()
方法读取数据时,可以执行日期转换。 parse_dates
参数,其中包含要读取为时间戳的列的列表:
pd.read_csv("../data/air_quality_no2_long.csv", parse_dates=["datetime"])
为什么会有这些? pandas.Timestamp
物件有用吗?让我们用一些示例案例来说明它的附加值。
我们正在处理的时间序列数据集的开始和结束日期是什么时候?
In [9]: air_quality["datetime"].min(), air_quality["datetime"].max()
Out[9]:
(Timestamp('2019-05-07 01:00:00+0000', tz='UTC'),
Timestamp('2019-06-21 00:00:00+0000', tz='UTC'))
使用 pandas.Timestamp
For DateTime使我们能够使用日期信息进行计算,并使它们具有可比性。因此,我们可以使用它来获得时间序列的长度:
In [10]: air_quality["datetime"].max() - air_quality["datetime"].min()
Out[10]: Timedelta('44 days 23:00:00')
结果是一个 pandas.Timedelta
对象,类似于 datetime.timedelta
并定义一个持续时间。
上的用户指南部分解释了Pandas支持的各种时间概念 time related concepts 。
我想将一个新专栏添加到
DataFrame
仅包含测量的月份In [11]: air_quality["month"] = air_quality["datetime"].dt.month In [12]: air_quality.head() Out[12]: 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
访问者。
中提供了现有Date属性的概述 time and date components overview table 。有关的更多详细信息 dt
类返回DateTime属性的访问器在 dt accessor 。
平均是多少? \(NO_2\) 每个测量地点一周中每天的浓度?
In [13]: air_quality.groupby( ....: [air_quality["datetime"].dt.weekday, "location"])["value"].mean() ....: Out[13]: datetime location 0 BETR801 27.875000 FR04014 24.856250 London Westminster 23.969697 1 BETR801 22.214286 FR04014 30.999359 ... 5 FR04014 25.266154 London Westminster 24.977612 6 BETR801 21.896552 FR04014 23.274306 London Westminster 24.859155 Name: value, Length: 21, dtype: float64
记住由提供的拆分-应用-组合模式
groupby
从 tutorial on statistics calculation ?在这里,我们想要计算给定的统计数据(例如,平均值 \(NO_2\) ) 每个工作日 和 对于每个测量位置 。要在工作日分组,我们使用DateTime属性weekday
(周一=0,周日=6)Timestamp
,它也可以通过dt
访问者。可以对地点和工作日进行分组,以拆分这些组合中每一个的平均值计算。危险
由于我们在这些示例中使用的是非常短的时间序列,因此分析不会提供具有长期代表性的结果!
绘制典型的 \(NO_2\) 我们一天中所有台站的时间序列都是这样的。换句话说,一天中每个小时的平均值是多少?
In [14]: fig, axs = plt.subplots(figsize=(12, 4)) In [15]: air_quality.groupby(air_quality["datetime"].dt.hour)["value"].mean().plot( ....: kind='bar', rot=0, ax=axs ....: ) ....: Out[15]: <AxesSubplot:xlabel='datetime'> In [16]: plt.xlabel("Hour of the day"); # custom x label using Matplotlib In [17]: plt.ylabel("$NO_2 (µg/m^3)$");
与前面的情况类似,我们希望计算给定的统计数据(例如,平均值 \(NO_2\) ) 一天中的每个小时 我们可以再次使用拆分-应用-合并的方法。对于本例,我们使用DateTime属性
hour
大Pandas的Timestamp
,它也可以通过dt
访问者。
将DateTime作为索引#
在 tutorial on reshaping , pivot()
用于重塑数据表,将每个测量位置作为单独的列:
In [18]: no_2 = air_quality.pivot(index="datetime", columns="location", values="value")
In [19]: no_2.head()
Out[19]:
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
访问器来获取时间序列属性,但可以直接在索引上使用这些属性:
In [20]: no_2.index.year, no_2.index.weekday
Out[20]:
(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))
其他一些优点是方便地细分时间段或调整曲线图上的时间尺度。让我们将这一点应用于我们的数据。
创建一个情节的 \(NO_2\) 从5月20日到5月21日底不同站点的数值
In [21]: no_2["2019-05-20":"2019-05-21"].plot();
通过提供一个 解析为日期时间的字符串 ,则可以在
DatetimeIndex
。
有关 DatetimeIndex
中的一节中提供了使用字符串的切片 time series indexing 。
将时间序列重采样到另一个频率#
将每个站点的当前每小时时间序列值聚合为每月最大值。
In [22]: monthly_max = no_2.resample("M").max() In [23]: monthly_max Out[23]: 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
使用DateTime索引处理时间序列数据的一种非常强大的方法是能够
resample()
将时间序列转换为另一频率(例如,将第二数据转换为5分钟数据)。
这个 resample()
方法类似于GROUP BY操作:
它提供基于时间的分组,使用字符串(例如
M
,5H
,…)它定义了目标频率它需要一个聚合函数,如
mean
,max
,…
中给出了用于定义时间序列频率的别名的概述 offset aliases overview table 。
定义后,时间序列的频率由 freq
属性:
In [24]: monthly_max.index.freq
Out[24]: <MonthEnd>
画一张日均的曲线图 \(NO_2\) 每个站点的价值。
In [25]: no_2.resample("D").mean().plot(style="-o", figsize=(10, 5));
关于时间序列的力量的更多细节 resampling
上的用户指南部分提供了 resampling 。
REMEMBER
有效的日期字符串可以使用以下命令转换为DateTime对象
to_datetime
函数或作为读取函数的一部分。属性支持计算、逻辑运算和方便的与日期相关的属性。
dt
访问者。A
DatetimeIndex
包含这些与日期相关的属性,并支持方便的切片。Resample
是改变时间序列频率的一种强有力的方法。
有关时间序列的完整概述,请参阅 time series and date functionality 。