【问题标题】:Plot with Matplotlib using List - Datetime - Different Behaviour on Format使用列表绘制 Matplotlib - 日期时间 - 格式上的不同行为
【发布时间】:2019-02-07 23:09:25
【问题描述】:

为什么 Matplotlib 对日期数据类型有这种奇怪的行为?

Matplotlib 允许您在本地绘制 python 日期时间实例,并且在大多数情况下可以很好地选择刻度位置和字符串格式。 来自documentation“修复常见日期烦恼”

我还阅读了this question,它给了我一些与Matplotlib Date Format 相关的线索。 我还阅读了有关matplotlibDatetime 的投票最多的问题,但我仍然不明白以下行为。

#timestamp is a <class 'list'>
timestamp=['2019-02-04', '2019-01-15', '2018-10-08', '2018-07-09',
           '2018-04-09', '2018-02-08', '2017-09-08', '2017-09-08',
           '2017-07-07', '2017-04-07', '2017-01-09', '2016-10-07',
           '2016-07-01', '2016-03-25', '2015-12-27', '2015-09-25',
           '2015-06-26', '2015-03-27', '2014-12-24', '2014-10-06',
           '2014-07-02', '2014-03-28', '2013-12-20', '2013-09-27',
           '2013-06-11', '2013-03-27', '2012-12-27', '2012-09-26',
           '2012-06-13', '2012-03-28', '2011-12-14', '2011-09-28',
           '2011-06-14', '2011-03-30', '2010-12-15', '2010-09-29',
           '2010-06-19', '2010-03-31', '2009-12-29', '2009-09-30',
           '2009-06-17', '2009-04-01', '2008-12-20', '2008-08-25',
           '2008-08-25', '2008-06-19', '2008-03-19', '2008-03-19',
           '2006-04-11', '2005-12-27', '2005-09-28', '2005-07-02',
           '2005-04-20', '2004-12-21', '2004-10-20', '2004-07-21',
           '2003-09-22', '2003-08-20', '2002-12-31']

#time_python is a <class 'datetime.datetime'>
time_python=[datetime.strptime(d, "%Y-%m-%d") for d in timestamp]
#time_series is a <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
time_series=pd.to_datetime(timestamp)

array=np.arange(1,len(timestamp)+1) 

time_2_num=mdates.date2num(time_series.to_pydatetime())

#First plot using the List Format as x axes
plt.subplot(411)
plt.bar(timestamp,array)
plt.xticks(rotation='vertical')

#Second plot using the padas Datatime Format as x axes
plt.subplot(412)
plt.bar(time_series,array)
plt.xticks(rotation='vertical')
plt.subplots_adjust(hspace = 1.2)

#Third plot using the DateTime Format as x axes 
plt.subplot(413)
plt.bar(time_python,array)
plt.xticks(rotation='vertical')
plt.subplots_adjust(hspace = 1.2)

#Fourth plot using the Matplot Date Format as x axes 
plt.subplot(414)
plt.bar(time_2_num,array)
plt.xticks(rotation='vertical')
plt.subplots_adjust(hspace = 1.2)

plt.gcf().autofmt_xdate()  

plt.show()

想要的结果显然是第一个情节。

我想更好地理解为什么 II、III、IV 图的条形图具有这种表示,与 I 不同。4 个图的 y 输入相同。

【问题讨论】:

    标签: python pandas datetime matplotlib


    【解决方案1】:

    首先,如果您删除线 plt.gcf().autofmt_xdate(),差异会变得更加明显,因为这会删除除最后一个图之外的所有标签。

    第一个情节

    第一个情节是“分类”情节。 x 轴的值是字符串。它们按照它们在输入列表/数组中出现的顺序一一显示,并且每个都有自己的标签。在这种情况下,matplotlib 不知道字符串代表日期,实际上您也可以提供一个水果列表 (["Apple", "Banana", "Cherry", ...])

    第二个/第三个情节

    这些是 matplotlib 中日期时间图的预期行为。 Matplotlib 同样适用于 datetimenumpy.datetime64 对象。从具有定义线性度量的线的意义上讲,该轴是真正的比例(即星期一和星期三之间的距离是星期六和星期日之间的距离的两倍)。关于此类日期时间轴的单位,documentation 状态

    Matplotlib 使用浮点数表示日期,指定自 0001-01-01 UTC 以来的天数,再加上 1。

    因为 matplotlib 识别日期时间输入,它会自动选择一个日期定位器和格式化程序,以便在有用的位置有刻度

    第四个情节

    第四个情节原则上与上述两个情节相同。 matplotlib 没有机会知道这些数字(如 731000)是用来表示日期的唯一区别(它们也可能是地球和卫星之间的距离)。

    您仍然可以通过手动设置定位器和格式化程序来获得与上述两个图中相同的外观,例如将以下行添加到最后一个情节

    loc = mdates.AutoDateLocator()
    plt.gca().xaxis.set_major_locator(loc)
    plt.gca().xaxis.set_major_formatter(mdates.AutoDateFormatter(loc))
    

    结果与第二、第三个图相同

    【讨论】:

    • 感谢@ImportanceOfBeingErnest 现在更清楚了。但是为什么我们在第一个图中绘制了 59 个条形图,而在其他三个图中只有 6 个?不同的 X 轴如何影响条形总数?
    • 几乎可以肯定,其他图中有 59 个条形图,但它们只有 0.8 天宽,因此不覆盖像素,因此不会出现。增加图形的 dpi,或将条形的宽度设置为更宽,记住单位是天。
    • 不,你有相同数量的酒吧。其中许多只是没有看到,因为默认情况下条形宽度小于一天。所以在这个具体的例子中,你有 16 年 ~= 5840 天。这些分布在大约 580 个像素上。因此,显示条形的概率大约为 10%。我建议给酒吧一个优势,将linewidth=1, edgecolor="C0" 添加到bar 命令。或者将条形加宽,width=15
    【解决方案2】:

    对于第一张图,您发送的是纯字符串 timestamp。 Matplotlib 将其视为字符串。如果您单独查看该图,您会发现标签只是来自timestamp 的字符串,顺序相同。

    其他 3 种方法将此字符串转换为时间戳,matplotlib 对此的处理方式不同。

    timestamp=['2019-02-04', '2019-01-15', '2018-10-08', '2018-07-09',
           '2018-04-09', '2018-02-08', '2017-09-08', '2017-09-08',
           '2017-07-07', '2017-04-07', '2017-01-09', '2016-10-07',
           '2016-07-01', '2016-03-25', '2015-12-27', '2015-09-25',
           '2015-06-26', '2015-03-27', '2014-12-24', '2014-10-06',
           '2014-07-02', '2014-03-28', '2013-12-20', '2013-09-27',
           '2013-06-11', '2013-03-27', '2012-12-27', '2012-09-26',
           '2012-06-13', '2012-03-28', '2011-12-14', '2011-09-28',
           '2011-06-14', '2011-03-30', '2010-12-15', '2010-09-29',
           '2010-06-19', '2010-03-31', '2009-12-29', '2009-09-30',
           '2009-06-17', '2009-04-01', '2008-12-20', '2008-08-25',
           '2008-08-25', '2008-06-19', '2008-03-19', '2008-03-19',
           '2006-04-11', '2005-12-27', '2005-09-28', '2005-07-02',
           '2005-04-20', '2004-12-21', '2004-10-20', '2004-07-21',
           '2003-09-22', '2003-08-20', '2002-12-31']
    
    array=np.arange(1,len(timestamp)+1) 
    plt.bar(timestamp,array)
    plt.xticks(rotation='vertical')
    fig = plt.gcf()
    fig.set_size_inches(18.5, 10.5)
    

    【讨论】:

    • 谢谢 :) 第一张图对我来说很清楚。我试图用其他数据类型来理解其他人:)
    猜你喜欢
    • 2019-12-14
    • 2020-04-07
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 2019-05-14
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多