【问题标题】:Ensuring first and last date ticks in x-axis - Matplotlib确保 x 轴上的第一个和最后一个日期刻度 - Matplotlib
【发布时间】:2021-02-12 10:18:34
【问题描述】:

目前我正在绘制从某个历史点到当前时间点的数据。例如,2019 年 1 月到今天(2021 年 2 月)。但是,我的 matplotlib 图表仅在 x 轴上显示 2019 年 1 月至 2021 年 1 月的日期(缺少最后一个 2 月的刻度),即使数据在实际图中绘制为今天的日期。

有没有什么办法可以保证第一个月和最后一个月总是反映在x轴图表上?换句话说,我希望 x 轴显示范围(包括)。

x 轴图片(缺少 2021 年 2 月)

此处绘制的数据是从 2019 年 1 月到今天(2 月 12 日)。

这是我的日期格式代码:

fig.autofmt_xdate()
date_format = mdates.DateFormatter("%b-%y")
ax.xaxis.set_major_formatter(date_format)

编辑:每个月后面的数字代表年份。

【问题讨论】:

  • 很难确定你想要的输出是什么。即使是每月的刻度也不能保证所有月份都显示为刻度(想想从 2018 年 3 月 29 日到 2020 年 3 月 2 日的范围 - matplotlib 必须选择一个月中的哪一天来放置刻度,所以结束月份或开始月份都不会是标记)。您可以在第一个和最后一个数据点设置一个刻度,并定义其间的刻度数。这会使图表更难阅读。您可以手动添加上个月,但这会使图表看起来不规则。那么,您如何想象最终的图形标注?
  • 我的回答是否提供了您正在寻找的解决方案?

标签: python matplotlib


【解决方案1】:

Matplotlib 使用有限数量的刻度。碰巧的是,2021 年 2 月没有使用刻度线。您可以尝试两件事。首先尝试将轴限制设置为今天过去:

ax.set_xlim(start_date, end_date)

您还可以尝试使用更多的刻度:

ax.set_xticks(np.arange(np.min(x), np.max(x), n_ticks))

其中n_ticks 代表刻度数,x 代表 x 轴上的值。

【讨论】:

  • 它代表的不是 2 月 22 日,而是 2021 年 2 月。而今天已经是 2021 年 2 月(我有今天的数据)。
  • 没错,但在您当前的刻度格式中,下一个刻度将是 2 月 21 日或 22 日,您还没有数据。
  • 为什么?我有 2019 年 1 月 1 日至 2021 年 2 月 12 日的数据。2021 年 2 月 21 日或 22 日有什么关系?谢谢。只是想理解。
  • Matplotlib 只是时不时地放置刻度。如果您添加额外的刻度,二月也会出现。我误解了你轴上的日期,所以 2 月的确切日期并不重要,但这不会改变修复。如果你想看到二月,你应该更多的滴答声。
【解决方案2】:

除了从头开始创建刻度外,我不知道有什么方法可以做到这一点。

在以下示例中,从第一个日期(1 月 25 日)的月份开始,从 pandas 数据帧的 DatetimeIndex 创建了所有 first-DatetimeIndex-timestamp-of-the-month 的列表到最后一个持续月份的开始。 step 变量会自动选择适当数量的刻度,并添加上个月,然后在重复时使用 np.unique 将其删除。标签是根据刻度时间戳格式化的。

此解决方案适用于小于每年的任何频率:

import numpy as np                 # v 1.19.2
import pandas as pd                # v 1.1.3
import matplotlib.pyplot as plt    # v 3.3.2

# Create sample dataset
start_date = '2019-01-25'
end_date = '2021-02-12'
rng = np.random.default_rng(seed=123) # random number generator
dti = pd.date_range(start_date, end_date, freq='D')
variable = 100 + rng.normal(size=dti.size).cumsum()
df = pd.DataFrame(dict(variable=variable), index=dti)

# Create matplotlib plot
fig, ax = plt.subplots(figsize=(10, 2))
ax.plot(df.index, df.variable)

# Create list of monthly ticks made of timestamp objects
monthly_ticks = [timestamp for idx, timestamp in enumerate(df.index)
                 if (timestamp.month != df.index[idx-1].month) | (idx == 0)]

# Select appropriate number of ticks and include last month
step = 1
while len(monthly_ticks[::step]) > 10:
    step += 1
ticks = np.unique(np.append(monthly_ticks[::step], monthly_ticks[-1]))

# Create tick labels from tick timestamps
labels = [timestamp.strftime('%b\n%Y') if timestamp.year != ticks[idx-1].year
          else timestamp.strftime('%b') for idx, timestamp in enumerate(ticks)]

plt.xticks(ticks, labels, rotation=0, ha='center');

如您所见,第一个月和最后几个月与相邻刻度的距离不规则。


如果您正在绘制具有不连续日期范围的时间序列(例如不包括周末和节假日)并且您没有使用 DatetimeIndex 作为 x 轴(例如例如:ax.plot(range(df.index.size), df.variable)) 以避免在短时间序列和/或非常宽的图中出现直线的间隙,然后将最后一行代码替换为:

plt.xticks([df.index.get_loc(tick) for tick in ticks], labels, rotation=0, ha='center');

【讨论】:

    猜你喜欢
    • 2020-06-03
    • 2020-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多