簡體   English   中英

帶有日期軸的Pandas / matplotlib圖顯示正確的日/月但錯誤的工作日/年

[英]Pandas/matplotlib plot with date-axis shows correct day/month but wrong weekday/year

我正在使用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 / parsing錯誤。

萬一它可能很重要(雖然我懷疑),我的語言環境是LC_TIME = en_US.UTF-8。

另外,根據https://www.timeanddate.com/date/weekday.html,06.02.0048當天實際上是星期二,所以繪制的年份實際上甚至不是0048年。

我真的很茫然,感謝任何願意檢查出來的人。

雖然我無法弄清楚它為什么不起作用,但它似乎與使用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再次顯示: 在此輸入圖像描述

所以問題仍然存在。

但是,您可以通過用index_col=0替換parse_dates=['date'] ,顯式創建matplotlib圖,並使用ticker.FixedFormatter更改mdates.DateFormatterticker.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()

在此輸入圖像描述

我也遇到了這個問題,但根本原因是不同的。

我在matplotlib DateFormatter類中進行了一些調試,以確定它實際運行的數據。 事實證明,針對postgres運行的pandas查詢正在生成日期對象而不是時間戳對象。 這導致日期被錯誤解析,使得年份不正確(解析為0046年而不是2018年)。

解決方案是更新查詢以將時間列強制轉換為時間戳,然后一切正常。

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

也就是說,我有點震驚的是,相關的庫不夠強大,無法處理postgres可以生成的各種日期表示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM