【问题标题】:Plotting time series in Matplotlib with month names (ex. January) and showing years beneath在 Matplotlib 中使用月份名称(例如一月)绘制时间序列并在下面显示年份
【发布时间】:2021-08-07 11:54:24
【问题描述】:

我目前正在使用以下数据绘制时间散点图(您可以使用这些数据来重现我的图)。要在 x 轴上绘制的数据是时间,特别是 datetime.datetime 对象 (tp_pass),而要在 y 轴上绘制的数据是 -180 到 180 (azip_pass) 之间的角度。另外,他们都是numpy.array

tp_pass=np.array([datetime.datetime(2019, 10, 29, 1, 4, 43),
        datetime.datetime(2019, 10, 31, 1, 11, 19),
        datetime.datetime(2019, 11, 20, 8, 26, 7),
        datetime.datetime(2019, 11, 20, 23, 50, 43),
        datetime.datetime(2019, 12, 10, 17, 5, 2),
        datetime.datetime(2020, 1, 2, 18, 23, 53),
        datetime.datetime(2020, 2, 13, 10, 33, 44),
        datetime.datetime(2020, 2, 20, 18, 57, 36),
        datetime.datetime(2020, 3, 25, 2, 49, 20),
        datetime.datetime(2020, 4, 10, 16, 44, 56),
        datetime.datetime(2020, 4, 18, 8, 25, 37),
        datetime.datetime(2020, 4, 19, 20, 39, 5),
        datetime.datetime(2020, 5, 3, 11, 54, 24),
        datetime.datetime(2020, 5, 4, 13, 7, 48),
        datetime.datetime(2020, 5, 30, 18, 13, 47),
        datetime.datetime(2020, 6, 13, 15, 51, 24),
        datetime.datetime(2020, 6, 24, 19, 47, 44),
        datetime.datetime(2020, 7, 30, 0, 35, 56),
        datetime.datetime(2020, 8, 1, 17, 9, 1),
        datetime.datetime(2020, 8, 3, 8, 31, 10),
        datetime.datetime(2020, 8, 18, 0, 3, 48),
        datetime.datetime(2020, 9, 15, 3, 41, 28),
        datetime.datetime(2020, 9, 20, 22, 13, 15),
        datetime.datetime(2020, 10, 3, 9, 31, 31),
        datetime.datetime(2020, 11, 6, 8, 56, 38),
        datetime.datetime(2020, 11, 15, 22, 37, 43),
        datetime.datetime(2020, 12, 10, 13, 19, 58),
        datetime.datetime(2020, 12, 20, 17, 23, 22),
        datetime.datetime(2020, 12, 24, 23, 43, 41),
        datetime.datetime(2021, 1, 12, 2, 39, 43),
        datetime.datetime(2021, 2, 13, 14, 7, 50),
        datetime.datetime(2021, 3, 2, 21, 22, 46)], dtype=object)

azip_pass=np.array([168.3472527 ,  160.09844756,  175.44976695,  159.46139347,
          168.4780719 ,  165.17699028,  158.22654417,  151.02735996,
          159.39235045,  164.8792118 ,  168.84217025,  166.09269395,
          -179.97929963,  163.3389004 ,  167.24285926,  167.08062597,
          163.71540408,  171.13687447,  163.61945117,  172.68473083,
          159.89871931,  166.72228462,  162.2774924 ,  166.13812415,
          14.7128006 ,   12.43499853,   11.86328998,   10.56097159,
          16.16589956,   12.81530251,   10.0220719 ,   4.21173499])

使用以下Python 脚本,我生成了情节。

import matplotlib.pyplot as plt
import numpy as np
import datetime
from matplotlib import dates
from matplotlib import rc
%config InlineBackend.print_figure_kwargs={'facecolor' : "w"}
rc('axes', edgecolor='k', linewidth="5.0")

fig, ax=plt.subplots(1, 1, figsize=(30, 10))
ax.xaxis.set_major_locator(dates.YearLocator())
ax.set_ylim(-185, 185)
ax.scatter(tp_pass, azip_pass, color="b", s=200, alpha=1.0, ec="k")
plt.xticks(fontsize=35)
plt.yticks([-180, -120, -60, 0, 60, 120, 180], ["${}^\circ$".format(x) for x in [-180, -120, -60, 0, 60, 120, 180]], fontsize=35)
plt.tight_layout()
plt.show()

绘图的 x 轴自动标记自我使用 matplotlib.dates.YearLocator() 以来的年份。实际上,我对它并不满意,还想在几年之间找到几个月。但是,我希望用他们的名字而不是数字来显示月份(例如 Jan、Feb、Mar 等)。下图的 x 轴显示了我想要实现的内容。这可以使用matplotlib吗?

添加 (2021-05-18)

使用matplotlib.dates.MonthLocator(),我能够制作月份显示。但是,年号消失了。有没有办法使用matplotlib 同时显示年份和月份(例如月份下的年份)?

fig, ax=plt.subplots(1, 1, figsize=(30, 10))
ax.xaxis.set_major_locator(dates.YearLocator()) # This line does not work
ax.xaxis.set_major_locator(dates.MonthLocator(bymonthday=15))
ax.xaxis.set_major_formatter(dates.DateFormatter('%b'))
ax.set_ylim(-185, 185)
ax.scatter(tp_pass, azip_pass, color="b", s=200, alpha=1.0, ec="k")
plt.xticks(fontsize=35)
plt.yticks([-180, -120, -60, 0, 60, 120, 180], ["${}^\circ$".format(x) for x in [-180, -120, -60, 0, 60, 120, 180]], fontsize=35)
plt.tight_layout()
plt.show()

添加(2021-05-19)

我发现 Patrick FitzGerald 对这个问题的回答 How to change the datetime tick label frequency for matplotlib plots? 非常有帮助。这个答案不需要使用辅助 x 轴,而是做我想做的事情。

【问题讨论】:

    标签: python-3.x matplotlib plot time-series


    【解决方案1】:

    您可以创建第二个 x 轴,使用它仅显示年份,同时使用原始 x 轴将月份显示为单词。这是使用您的示例的这种方法。它看起来像这样。

    import matplotlib.pyplot as plt
    import numpy as np
    import datetime
    from matplotlib import dates as mdates
    
    # Using Data from OP: tp_pass and azip_pass
    
    # Creating your plot
    
    fig, ax=plt.subplots(1, 1, figsize=(30, 10))
    
    ax.set_ylim(-185, 185)
    ax.scatter(tp_pass, azip_pass, color="b", s=200, alpha=1.0, ec="k")
    
    # Minor ticks every month.
    fmt_month = mdates.MonthLocator()
    # Minor ticks every year.
    fmt_year = mdates.YearLocator()
    
    ax.xaxis.set_minor_locator(fmt_month)
    # '%b' to get the names of the month
    ax.xaxis.set_minor_formatter(mdates.DateFormatter('%b'))
    ax.xaxis.set_major_locator(fmt_year)
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%b'))
    
    # fontsize for month labels
    ax.tick_params(labelsize=20, which='both')
    # create a second x-axis beneath the first x-axis to show the year in YYYY format
    sec_xaxis = ax.secondary_xaxis(-0.1)
    sec_xaxis.xaxis.set_major_locator(fmt_year)
    sec_xaxis.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
    
    # Hide the second x-axis spines and ticks
    sec_xaxis.spines['bottom'].set_visible(False)
    sec_xaxis.tick_params(length=0, labelsize=35)
    
    plt.yticks([-180, -120, -60, 0, 60, 120, 180], ["${}^\circ$".format(x) for x in [-180, -120, -60, 0, 60, 120, 180]], fontsize=35)
    plt.tight_layout()
    plt.show()
    

    【讨论】:

      【解决方案2】:

      我建议使用 ConciseDateFormatter https://matplotlib.org/stable/gallery/ticks_and_spines/date_concise_formatter.html 如果您真的希望每个月都定位,请使用自动定位器获取更多滴答声:

      fig, ax=plt.subplots(1, 1, figsize=(8, 4), constrained_layout=True)
      plt.rcParams['date.converter'] = 'concise'
      ax.xaxis.set_major_locator(mdates.AutoDateLocator(minticks=12, maxticks=20))
      
      ax.set_ylim(-185, 185)
      ax.scatter(tp_pass, azip_pass, color="b", s=200, alpha=1.0, ec="k")
      # plt.xticks(fontsize=35)
      plt.yticks([-180, -120, -60, 0, 60, 120, 180], ["${}^\circ$".format(x) for x in [-180, -120, -60, 0, 60, 120, 180]])
      plt.show()
      

      【讨论】:

      • 另外,我不清楚你为什么把所有东西都做得这么大? 30 英寸的人偶通常没有用处……
      • 谢谢!但我希望每个月都出现(在你的情节中,一月被年份取代)所以使用辅助 x 轴更有用。关于图形大小,我通常在 Jupyter Notebook 环境中工作并以交互方式检查图形,但除非我设置 width=30,否则它看起来太小了。
      • 另外,我最终想出了如何使用ConciseDateFormatter 来实现我想做的事情(这个问题的第二个答案stackoverflow.com/questions/45704366/…)。
      • 我的意思是如果每隔一个月被标记,除了 12 月和 2 月之间的那个被标记为 2020 年,我认为它很清楚发生了什么。
      猜你喜欢
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-23
      • 2018-12-02
      • 2021-08-28
      相关资源
      最近更新 更多