matplotlib 时间坐标轴的生成
在 matplotlib
中,当需要用到日期作为坐标轴时需要引入 matplotlib
的日期库 dates
,有时候需要自定义时间间隔来显示坐标轴,而 matplotlib
往往不能正确的按照给定的时间间隔把坐标显示出来。matplotlib
的官方文档给出了简单的例子,本文给出了一个时间间隔为 10min
的例子,并详细说明了每一行代码,通过这个小例子能更加精确的细分时间刻度并让 matplotlib
正确地显示出来。
先来看看最终的效果图
完整的参考代码如下:
import matplotlib.pyplot as plt
import matplotlib.dates as md
from matplotlib.dates import MINUTELY
from matplotlib.dates import AutoDateLocator
import pandas as pd
import numpy as np
# 通过 figsize 调整图表的长宽比例,使得坐标轴上的刻度不至于太挤
fig = plt.figure(figsize=(21, 7))
ax = fig.add_subplot()
# 给定的日期格式可以有多种 20201001 2020-10-01 2020/10/01
start_time_string = "20201001 10:10:10"
end_time_string = "20201001 20:00:00"
# 根据日期生成时间轴
# freq 用来指明以多大间隔划分整个时间区间
# 10T/10min 按 10 分钟划分,同理其他常见的时间跨度有
# W 周、D 天(默认值)、H 小时、S 秒、L/ms 毫秒、U/us 微秒、N 纳秒
# 其他具体的详见 https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases
x = pd.date_range(start=start_time_string, end=end_time_string, freq="10T")
# 二维上的点是相互对应的,根据 x 的个数随机生成 y
y = np.random.random(len(x))
# x, y 按离散的关系添加在图中
ax.plot(x, y)
# 自定义时间刻度如何显示
def time_ticks(x, pos):
# 在 pandas 中,按 10min 生成的时间序列与 matplotlib 要求的类型不一致
# 需要转换成 matplotlib 支持的类型
x = md.num2date(x)
# 时间坐标是从坐标原点到结束一个一个标出的
# 如果是坐标原点的那个刻度则用下面的要求标出刻度
if pos == 0:
# %Y-%m-%d
# 时间格式化的标准是按 2020-10-01 10:10:10.0000 标记的
fmt = '%Y-%m-%d %H:%M:%S.%f'
# 如果不是是坐标原点的那个刻度则用下面的要求标出刻度
else:
# 时间格式化的标准是按 10:10:10.0000 标记的
fmt = '%H:%M:%S.%f'
# 根据 fmt 的要求画时间刻度
label = x.strftime(fmt)
# 当 fmt 有%s时需要下面的代码
label = label.rstrip("0")
label = label.rstrip(".")
# 截断了秒后面的 .000
return label
# 根据自己定义的方式去画时间刻度
formatter = plt.FuncFormatter(time_ticks)
# 在图中应用自定义的时间刻度
ax.xaxis.set_major_formatter(formatter)
# minticks 需要指出,值的大小决定了图是否能按 10min 为单位显示
# 值越小可能只能按小时间隔显示
locator = AutoDateLocator(minticks=20)
# pandas 只生成了满足 10min 的 x 的值,而指定坐标轴以多少的时间间隔画的是下面的这行代码
# 如果是小时,需要在上面导入相应的东东 YEARLY, MONTHLY, DAILY, HOURLY, MINUTELY, SECONDLY, MICROSECONDLY
# 并按照下面的格式照葫芦画瓢
locator.intervald[MINUTELY] = [10] # 10min 为间隔
ax.xaxis.set_major_locator(locator=locator)
# 旋转刻度坐标的字符,使得字符之间不要太拥挤
fig.autofmt_xdate()
plt.show()