跳至主要内容

Matplotlib 时间序列折线图

本教程介绍如何在 matplotlib 中创建和自定义时间序列折线图。
· 8分钟 阅读

使用 AI 探索

时间序列是按时间顺序索引的一组数据观测值。这些观测值通常(但不一定)以固定时间间隔记录。时间序列常用于银行、交易、市场营销、科学等行业。最典型的可视化方式是折线图:时间在 x 轴上,测量值在 y 轴上。

在本教程中,我们将探索如何在 Python 主要绘图库 matplotlib 中创建和自定义时间序列折线图。

使用 matplotlib 开始时间序列绘图

导入库并加载数据

首先,我们将导入必要的 Python 库并加载数据——来自 Kaggle 的数据集 Daily Exchange Rates per Euro 1999-2023。我们还会进行一些基本的数据清洗:

import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
from datetime import datetime

df = pd.read_csv('euro-daily-hist_1999_2022.csv')
df = df.iloc[:, [0, 4, 28, -2]]
df.columns = ['Date', 'CAD', 'NZD', 'USD']

for col in ['CAD', 'NZD', 'USD']:
    df = df[df[col] != '-']
    df[col] = pd.to_numeric(df[col])
   
df = df[df['Date'] >= '2022-12-01'].reset_index(drop=True)
print(df.head(3))
print(f'\nThe date range: {df.Date.min()}/{ df.Date.max()}')

输出:

Date     CAD     NZD     USD
0  2023-01-27  1.4479  1.6759  1.0865
1  2023-01-26  1.4568  1.6799  1.0895
2  2023-01-25  1.4544  1.6792  1.0878

The date range: 2022-12-01/2023-01-27

将日期/时间字符串转换为 datetime 对象

要高效处理时间序列,我们需要使用 pandas.to_datetime 函数将日期或时间字符串转换为 datetime 对象:

df['Date'] = pd.to_datetime(df['Date'])
print(df['Date'].dtypes)

输出:

datetime64[ns]

如果您需要复习如何在 Python 中处理时间序列,Manipulating Time Series Data in Python 课程可能对您有帮助。

将 datetime 列设为数据框索引

现在,让我们使用 set_index 方法将 Date 列设为数据框索引:

df = df.set_index('Date')
print(df.head(3))

输出:

              CAD     NZD     USD
Date                             
2023-01-27  1.4479  1.6759  1.0865
2023-01-26  1.4568  1.6799  1.0895
2023-01-25  1.4544  1.6792  1.0878

创建基础的单线 matplotlib 时间序列图

要创建基础的时间序列折线图,我们使用标准的 matplotlib.pyplot.plot(x, y) 方法:

plt.plot(df.index, df['CAD'])

输出:

image1.png

创建多线 matplotlib 时间序列图

要创建多线时间序列图,只需将 matplotlib.pyplot.plot(x, y) 方法按需调用多次: 

plt.plot(df.index, df['CAD'])
plt.plot(df.index, df['NZD'])
plt.plot(df.index, df['USD'])

image4.png

使用 for 循环可以让上述代码更简洁:

for col in ['CAD', 'NZD', 'USD']:
    plt.plot(df.index, df[col])

输出: 

image4.png

自定义 matplotlib 时间序列图

为使时间序列折线图更易读、更有说服力,我们需要对其进行自定义。可以应用一些常见的 matplotlib 调整,如自定义画布大小、添加并自定义图表标题与坐标轴标签、修改线条属性、添加并自定义标记等。还有一些仅针对时间序列折线图的调整,例如自定义时间轴刻度及其标签,或高亮特定时间区间。

自定义画布与坐标轴

使用标准的 matplotlib 方法,我们可以通过多种方式自定义时间序列折线图的画布与坐标轴,下面的代码注释进行了说明:

# Adjusting the figure size
fig = plt.subplots(figsize=(16, 5))

# Creating a plot
plt.plot(df.index, df['CAD'])

# Adding a plot title and customizing its font size
plt.title('EUR-CAD rate', fontsize=20)

# Adding axis labels and customizing their font size
plt.xlabel('Date', fontsize=15)
plt.ylabel('Rate', fontsize=15)

# Rotaing axis ticks and customizing their font size
plt.xticks(rotation=30, fontsize=15)

# Changing the plot resolution - zooming in the period from 15.12.2022 till 15.01.2023
plt.xlim(pd.Timestamp('2022-12-15'), pd.Timestamp('2023-01-15'))

输出: 

image8.png

自定义线条属性

与一般折线图类似,可以更改时间序列折线图的线条属性,如颜色、样式或宽度:

plt.plot(df.index, df['CAD'], color='green', linestyle='dashed', linewidth=3)

输出:

image5.png

添加并自定义标记

与任何折线图一样,我们可以在时间序列折线图上添加标记,并自定义其形状、颜色、边框颜色和大小:

plt.plot(df.index, df['CAD'], marker='o', markerfacecolor='yellow', markeredgecolor='red', markersize=8)

image9.png

自定义时间轴刻度

先创建一个带有基本自定义项的 matplotlib 时间序列折线图:

fig = plt.subplots(figsize=(16, 5))
plt.plot(df.index, df['CAD'])
plt.title('EUR-CAD rate', fontsize=20)
plt.xlabel('Date', fontsize=15)
plt.ylabel('Rate', fontsize=15)
plt.xlim(df.index.min(), df.index.max())

输出: 

image7.png

可以看到,matplotlib 默认会显示一些随机的刻度及其标签。不过我们可能希望控制时间轴上显示哪些刻度。在这种情况下,需要将所需日期(或时间)的字符串或 pandas 时间戳列表传给 matplotlib.pyplot.xticks 方法:

fig = plt.subplots(figsize=(16, 5))
plt.plot(df.index, df['CAD'])
plt.title('EUR-CAD rate', fontsize=20)
plt.xlabel('Date', fontsize=15)
plt.ylabel('Rate', fontsize=15)
plt.xlim(df.index.min(), df.index.max())

# Defining and displaying time axis ticks
ticks = ['2022-12-05', '2023-01-02', '2023-01-20']
plt.xticks(ticks)

输出: 

image6.png

如上所示,matplotlib 展示了选定的刻度,并自动为其添加了标签。

如果我们希望显示所有刻度,则应将时间序列的索引列表传给 matplotlib.pyplot.xticks 方法:

fig = plt.subplots(figsize=(16, 5))
plt.plot(df.index, df['CAD'])
plt.title('EUR-CAD rate', fontsize=20)
plt.xlabel('Date', fontsize=15)
plt.ylabel('Rate', fontsize=15)
plt.xlim(df.index.min(), df.index.max())

# Defining and displaying all time axis ticks
ticks = list(df.index)
plt.xticks(ticks, rotation=45)

输出: 

image2.png

自定义时间轴刻度标签

上图的时间轴刻度标签可能显得过于密集。我们可以对其进行格式化以提升可读性。为此,可以使用 matplotlib.dates.DateFormatter 类,并传入一个 strftime 格式字符串,指定希望日期/时间的显示方式。然后,将该格式器传给 matplotlib.axis.XAxis.set_major_formatter 方法:

fig, ax = plt.subplots(figsize=(16, 5))
plt.plot(df.index, df['CAD'])
plt.title('EUR-CAD rate', fontsize=20)
plt.xlabel('Date', fontsize=15)
plt.ylabel('Rate', fontsize=15)
plt.xlim(df.index.min(), df.index.max())
ticks = list(df.index)
plt.xticks(ticks, rotation=45)

# Formatting time axis tick labels
ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%b %d'))

输出: 

image10.png

此文档页面提供了所有可用 strftime 格式代码的完整列表。

高亮特定时间区间

有时,我们可能希望在时间序列折线图上对某些时间区间进行着色高亮。为此可以使用 matplotlib.pyplot.axvspan 方法。它需要两个必填参数:感兴趣区间的起止时间点(datetime 格式)。此外,该方法还可接收一些可选参数以自定义高亮区域的外观,如颜色、边框颜色、透明度、线宽或填充样式。

让我们将此技巧应用到上一节的图表中:

fig, ax = plt.subplots(figsize=(16, 5))
plt.plot(df.index, df['CAD'])
plt.title('EUR-CAD rate', fontsize=20)
plt.xlabel('Date', fontsize=15)
plt.ylabel('Rate', fontsize=15)
plt.xlim(df.index.min(), df.index.max())
ticks = list(df.index)
plt.xticks(ticks, rotation=45)
ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%b %d'))

# Highlighting the time period from 15.12.2022 to 1.01.2023 and customizing the shaded area
plt.axvspan(datetime(2022, 12, 15), datetime(2023, 1, 1), facecolor='yellow', alpha=0.5, hatch='/', edgecolor='red', linewidth=5)

输出: 

image11.png

将 matplotlib 时间序列折线图保存为文件

我们可以选择将时间序列折线图保存为图像文件,而不仅仅是显示出来。为此,使用 matplotlib.pyplot.savefig 方法并传入文件名。比如,回到我们最初的基础图:

plt.plot(df.index, df['CAD'])

# Saving the resulting plot to a file
plt.savefig('time series line plot.png')

image1.png

上面我们将图表保存为名为 time series line plot.png 的文件,并与当前程序位于同一目录。

结语

总之,在本教程中,我们讨论了如何在 matplotlib 中创建和自定义时间序列折线图,涵盖了常见的 matplotlib 方法以及仅适用于时间序列可视化的更高级方法。

在掌握这些基础技巧后,您可能希望更深入地学习如何在 Python 中处理并可视化时间序列数据。您可以考虑以下全面、适合初学者、端到端的资源:

主题