【问题标题】:why doesn't matplotlib support datetime64为什么 matplotlib 不支持 datetime64
【发布时间】:2016-09-11 09:54:23
【问题描述】:

所以我有一个在 x 轴上打印小数而不是日期的图。我已经对 * 进行了研究,并且读到 matplotlib 根本不处理 datetime64 而无需围绕它进行编码。我似乎无法找出原因?请注意,我不是在问如何解决它,而是为什么存在问题,我知道这是有充分理由的,但我似乎无法找出原因。

我的代码行看起来像这样,我没有显示程序的其余部分,因为它与我提出的问题无关。

my_dates =  np.array([d[0] for d in data]).astype('datetime64[D]')

【问题讨论】:

    标签: python-3.x matplotlib


    【解决方案1】:

    我读到的一些原因是由于以某种保持稳定的方式实现此功能所隐含的困难和时间。如您所见here,该提案已经过时(至少自 2012 年以来)。

    已经提出了几种解决方法,您会在 SO 中找到示例,例如 thisthis

    至于 matplotlib lib 本身,您甚至会发现一些似乎可以作为初始原型使用的解决方案。这是由 agijsberts 在此讨论 here 中发布的。尽管问题出在pandas 跟踪器中,但实际上该解决方案似乎根本不需要 pandas。

    from matplotlib import units, dates
    from matplotlib import pyplot as plt
    from numpy import datetime64, timedelta64, arange, ndarray, dtype
    from numpy.random import rand
    import datetime
    
    resolution_scale = {
        dtype('datetime64[ns]'): 1e-9,
        dtype('datetime64[us]'): 1e-6,
        dtype('datetime64[ms]'): 1e-3,
        dtype('datetime64[s]'): 1,
        dtype('datetime64[m]'): 60,
        dtype('datetime64[h]'): 60 * 60,
        dtype('datetime64[D]'): 24 * 60 * 60,
    }
    
    class Datetime64Converter(dates.DateConverter):
        @staticmethod
        def convert(values, unit, axis):
            if isinstance(values, ndarray) and issubclass(values.dtype.type, datetime64):
                return dates.epoch2num(values.view('i8') * resolution_scale[values.dtype])
            elif isinstance(values, datetime.date):
                return dates.date2num(values)
            else:
                return values
    
    units.registry[datetime64] = Datetime64Converter
    
    a = arange('2014-01-01', '2014-01-07', timedelta64(1, 'D'), dtype='datetime64[D]')
    b = rand(len(a))
    for i, r in enumerate(('ns', 'us', 'ms', 's', 'm', 'h', 'D')):
        plt.plot(a.astype('datetime64[{0}]'.format(r)), b + i, label=r)
    plt.legend()
    plt.show()
    

    然而,即使这样,我仍然没有听说过这样做的实际妥协(尽管请注意,我也没有让自己了解情况)。就我个人而言,我会说未实施的原因仅仅是因为它不在任何优先级列表中

    【讨论】:

    • 非常感谢@armatita 非常感谢您抽出宝贵的时间。你证实了我的怀疑,但想确认一下。再次感谢
    【解决方案2】:

    从 Matplotlib >= 2.2.2(也可能是较低版本)开始,numpy.datetime64 可以直接绘制。

    以下产生所需的输出

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.arange('2014-01-01', '2014-01-07', np.timedelta64(1, 'D'), dtype='datetime64[D]')
    y = np.random.rand(len(x))
    
    plt.plot(x,y)
    plt.show()
    

    【讨论】: