【问题标题】:Discontinuous timeseries plot with dates on x-axisx 轴上带有日期的不连续时间序列图
【发布时间】:2013-09-24 21:29:53
【问题描述】:

我获得了几个月的数据,但在几个月之间丢失了数据。如果我将整个数据集绘制在一个图中(中间有很多空白区域),这看起来很奇怪。 我编写了一个小示例脚本来展示它是如何工作的(基于:Python/Matplotlib - Is there a way to make a discontinuous axis?

问题:我无法让 x 轴使用相同的日期格式! ax 或 ax2 中的任何一个都是正确的,但绝不是两者都正确。 你有什么想法吗?

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import datetime

def getDates(startdate, enddate):
    days  = (enddate + datetime.timedelta(days=1) - startdate).days
    dates = [ startdate + datetime.timedelta(days=x) for x in range(0,days) ]
    return dates

dates1 = getDates(datetime.datetime(2013,1,1), datetime.datetime(2013,1,31))
dates2 = getDates(datetime.datetime(2013,3,1), datetime.datetime(2013,3,31))
dates = dates1+dates2
data = np.arange(len(dates))

Locator = mpl.dates.DayLocator(interval=5)
Formatter = mpl.dates.DateFormatter('%d-%m-%y')

fig,(ax,ax2) = plt.subplots(1,2,sharey=True)
fig.subplots_adjust(wspace=0.05)
fig.set_size_inches(10,3)
ax.plot(dates, data)
ax2.plot(dates, data)
ax.legend(loc=1)
ax.set_ylim( 0, 61 )
ax.set_xlim( datetime.datetime(2013,1,1), datetime.datetime(2013,1,31) )
ax2.set_xlim( datetime.datetime(2013,3,1), datetime.datetime(2013,3,31) )
labels = ax.get_xticklabels()
for label in labels: label.set_rotation(30)
labels = ax2.get_xticklabels()
for label in labels: label.set_rotation(30) 
ax.spines['right'].set_visible(False)
ax2.spines['left'].set_visible(False)
ax.tick_params(right='off')
ax2.tick_params(left='off')
ax2.yaxis.tick_right()
ax.xaxis.set_major_locator(Locator)
ax.xaxis.set_major_formatter(Formatter)
ax2.xaxis.set_major_locator(Locator)
ax2.xaxis.set_major_formatter(Formatter)
plt.savefig("test.png", bbox_inches='tight')

结果:

【问题讨论】:

  • 请不要折叠for 循环到一行,这是不好的风格,会混淆你的读者(比如我)

标签: python numpy matplotlib


【解决方案1】:

您发现了一个关于matplotlib 内部的有趣细节。您传递给set_major_locator 的定位器对象 轴使用的对象来确定将它的刻度放在哪里,axes 都使用相同的定位器对象。作为绘制的一部分,定位器会根据轴的限制生成一个刻度线列表,当它完成第二个轴时意味着在第一个轴上没有刻度线可见。您只需要传入不同的(单独的实例化)定位器对象,在此处使用 copy 完成。

import datetime
import copy

def getDates(startdate, enddate):
    days  = (enddate + datetime.timedelta(days=1) - startdate).days
    dates = [ startdate + datetime.timedelta(days=x) for x in range(0, days) ]
    return dates

dates1 = getDates(datetime.datetime(2013, 1, 1), datetime.datetime(2013, 1, 31))
dates2 = getDates(datetime.datetime(2013, 3, 1), datetime.datetime(2013, 3, 31))
dates = dates1+dates2
data = np.arange(len(dates))

Locator = mpl.dates.DayLocator(interval=5)
Formatter = mpl.dates.DateFormatter('%d-%m-%y')

fig, (ax, ax2) = plt.subplots(1, 2, sharey=True, tight_layout=True)
fig.subplots_adjust(wspace=0.05)
fig.set_size_inches(10, 3, forward=True)

ax.plot(dates, data)
ax2.plot(dates, data)

ax.legend(loc=1)
ax.set_ylim(0, 61)
ax.set_xlim(datetime.datetime(2013, 1, 1), datetime.datetime(2013, 1, 31))
ax2.set_xlim(datetime.datetime(2013, 3, 1), datetime.datetime(2013, 3, 31))

labels = ax.get_xticklabels()
for label in labels:
    label.set_rotation(30)
labels = ax2.get_xticklabels()
for label in labels:
    label.set_rotation(30)

ax.spines['right'].set_visible(False)
ax2.spines['left'].set_visible(False)
ax.tick_params(right='off')
ax2.tick_params(left='off')
ax2.yaxis.tick_right()


# note the copy here
ax.xaxis.set_major_locator(copy.copy(Locator))
ax.xaxis.set_major_formatter(copy.copy(Formatter))
ax2.xaxis.set_major_locator(copy.copy(Locator))
ax2.xaxis.set_major_formatter(copy.copy(Formatter))

【讨论】:

    猜你喜欢
    • 2015-08-13
    • 2023-04-02
    • 2019-09-23
    • 2011-06-18
    • 2019-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    相关资源
    最近更新 更多