matplotlib / pandas中日期的内部表示形式不一致

时间:2018-06-22 12:37:58

标签: pandas matplotlib python-datetime

import pandas as pd

index = pd.to_datetime(['2016-05-01', '2016-11-01', '2017-05-02'])
data = pd.DataFrame({'a': [1, 2, 3],
                     'b': [4, 5, 6]}, index=index)
ax = data.plot()
print(ax.get_xlim())

# Out: (736066.7, 736469.3)

现在,如果我们更改最后日期。

index = pd.to_datetime(['2016-05-01', '2016-11-01', '2017-05-01'])
data = pd.DataFrame({'a': [1, 2, 3],
                     'b': [4, 5, 6]}, index=index)
ax = data.plot()
print(ax.get_xlim())

# Out: (184.8, 189.2)

第一个示例似乎与matplotlib docs一致:

  

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

为什么第二个示例返回看起来完全不同的东西?我正在使用pandas 0.22.0版和matplotlib 2.2.2。版。

2 个答案:

答案 0 :(得分:2)

在第二个示例中,如果您查看图表,而不是给出日期,则matplotlib给出的是四分之一值:Plot for second example

在这种情况下,日期正好是六个月,因此相隔两个季度,这大概就是为什么您看到此行为的原因。虽然我在文档中找不到它,但在这种情况下xlim给出的数字与Unix Epoch(1970年1月1日)以来的季度数一致。

答案 1 :(得分:0)

熊猫使用不同的单位表示轴上的日期和时间,具体取决于所使用的日期/时间范围。这意味着正在使用不同的定位器。

在第一种情况下,

print(ax.xaxis.get_major_locator())
# Out: pandas.plotting._converter.PandasAutoDateLocator

在第二种情况下

print(ax.xaxis.get_major_locator())
# pandas.plotting._converter.TimeSeries_DateLocator

您可以通过PandasAutoDateLocator参数迫使熊猫始终使用x_compat

df.plot(x_compat=True)

这将确保始终获得与matplotlib.dates约定一致的日期时间定义。

缺点是,这消除了不错的季度滴答声

enter image description here

并用标准的勾号代替

enter image description here

另一方面,这将允许使用非常可定制的matplotlib.dates代码和格式化程序。例如获取季度刻度/标签

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
import pandas as pd

index = pd.to_datetime(['2016-05-01', '2016-11-01', '2017-05-01'])
data = pd.DataFrame({'a': [1, 2, 3],
                     'b': [4, 5, 6]}, index=index)
ax = data.plot(x_compat=True)

# Quarterly ticks
ax.xaxis.set_major_locator(mdates.MonthLocator((1,4,7,10)))

# Formatting:
def func(x,pos):
    q = (mdates.num2date(x).month-1)//3+1
    tx = "Q{}".format(q)
    if q == 1:
        tx += "\n{}".format(mdates.num2date(x).year)
    return tx
ax.xaxis.set_major_formatter(mticker.FuncFormatter(func))
plt.setp(ax.get_xticklabels(), rotation=0, ha="center")

plt.show()

enter image description here