【问题标题】:Pandas/matplotlib plot with date-axis shows correct day/month but wrong weekday/year带有日期轴的 Pandas/matplotlib 图显示正确的日/月但错误的工作日/年
【发布时间】:2017-08-22 17:42:40
【问题描述】:

我正在使用 pandas 加载 CSV 数据,其中一列采用以下形式 格式为 '%a %d.%m.%Y' 的日期(例如 'Mon 06.02.2017'),然后尝试 制作一些图,其中 x 轴根据日期标记。

绘图过程中出现问题,因为日期标签错误; 例如CSV/DataFrame 中的“Mon 06.02.2017”显示为“Thu” 06.02.0048' 在绘图轴上。

这是一个 MWE。这是文件“data.csv”:

Mon 06.02.2017  ;  1  ;  2  ;  3
Tue 07.02.2017  ;  4  ;  5  ;  6
Wed 08.02.2017  ;  7  ;  8  ;  9
Thu 09.02.2017  ; 10  ; 11  ; 12
Fri 10.02.2017  ; 13  ; 14  ; 15
Sat 11.02.2017  ; 16  ; 17  ; 18
Sun 12.02.2017  ; 19  ; 20  ; 21
Mon 13.02.2017  ; 22  ; 23  ; 24
Tue 14.02.2017  ; 25  ; 26  ; 27
Wed 15.02.2017  ; 28  ; 29  ; 30
Thu 16.02.2017  ; 31  ; 32  ; 33

这是解析/绘图代码'plot.py':

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


df = pd.read_csv(
        'data.csv',
        sep='\s*;\s*',
        header=None,
        names=['date', 'x', 'y', 'z'],
        parse_dates=['date'],
        date_parser=lambda x: pd.datetime.strptime(x, '%a %d.%m.%Y'),
        # infer_datetime_format=True,
        # dayfirst=True,
        engine='python',
)

# DataFrame 'date' Series looks fine
print df.date

ax1 = df.plot(x='date', y='x', legend=True)
ax2 = df.plot(x='date', y='y', ax=ax1, legend=True)
ax3 = df.plot(x='date', y='z', ax=ax1, legend=True)

ax1.xaxis.set_minor_locator(mdates.DayLocator(interval=1))
ax1.xaxis.set_minor_formatter(mdates.DateFormatter('%a %d.%m.%Y'))
ax1.xaxis.grid(True, which='minor')

plt.setp(ax1.xaxis.get_minorticklabels(), rotation=45)
plt.setp(ax1.xaxis.get_majorticklabels(), visible=False)
plt.tight_layout()

plt.show()

请注意,DataFrame.date 系列似乎包含正确的日期,所以 这可能是 matplotlib 问题,而不是 pandas/解析错误。

以防万一(尽管我怀疑),我的语言环境是 LC_TIME = en_US.UTF-8。

另外,根据https://www.timeanddate.com/date/weekday.html,当天 06.02.0048 实际上是星期二,所以不知何故,绘制的年份甚至不是 真的是 0048 年。

我真的很茫然,感谢任何愿意检查的人。

【问题讨论】:

    标签: python pandas matplotlib


    【解决方案1】:

    虽然我无法真正弄清楚为什么它不起作用,但它似乎与使用 pandas 进行绘图与仅使用 matplotlib 以及可能是 mdates.DateFormatter...

    当我注释掉格式行时,它似乎开始工作了:

    # ax1.xaxis.set_minor_locator(mdates.DayLocator(interval=1))
    # ax1.xaxis.set_minor_formatter(mdates.DateFormatter('%a %d.%m.%Y'))
    # ax1.xaxis.grid(True, which='minor')
    # 
    # plt.setp(ax1.xaxis.get_minorticklabels(), rotation=45)
    # plt.setp(ax1.xaxis.get_majorticklabels(), visible=False)
    

    Pandas 自动绘制日期可以正常工作,但调用任何 matplotlib 函数都会破坏日期。只有注释掉 #plt.setp(ax1.xaxis.get_majorticklabels(), visible=False),才会绘制 Pandas 和 Matplotlib xaxis,奇数 0048 再次出现:

    所以问题仍然存在。

    但是,您可以通过将 parse_dates=['date'] 替换为 index_col=0、显式创建 matplotlib 图形并将 mdates.DateFormatter 更改为 ticker.FixedFormatter 来规避此问题:

    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    import matplotlib.ticker as ticker
    
    df = pd.read_csv(
        'data.csv',
        sep='\s*;\s*',
        header=None,
        names=['date', 'x', 'y', 'z'],
        index_col=0,
        date_parser=lambda x: pd.to_datetime(x, format='%a %d.%m.%Y'),
        engine='python'
    )
    
    ax = plt.figure().add_subplot(111)
    ax.plot(df)
    
    ticklabels = [item.strftime('%d-%m-%y') for item in df.index]
    ax.xaxis.set_major_locator(mdates.DayLocator(interval=1))
    ax.xaxis.set_major_formatter(ticker.FixedFormatter(ticklabels))
    
    plt.xticks(rotation='90')
    ax.xaxis.grid(True, which='major')
    
    plt.tight_layout()
    
    plt.show()
    

    【讨论】:

      【解决方案2】:

      我也遇到了这个问题,但根本原因不同。

      我在 matplotlib DateFormatter 类中进行了一些调试,以找出它实际操作的数据。事实证明,针对 postgres 运行的 pandas 查询生成的是日期对象而不是时间戳对象。这导致日期被错误解析,导致年份不正确(解析为 0046 年而不是 2018 年)。

      解决方案是更新查询以将时间列转换为时间戳,然后一切正常。

      SELECT start_time::timestamp at time zone '{{timezone}}' as "Start Time" ...
      

      也就是说,我有点震惊,相关库不够健壮,无法处理 postgres 可以生成的不同类型的日期表示。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-11
        • 1970-01-01
        • 2021-12-22
        • 1970-01-01
        • 2020-07-08
        • 2018-04-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多