Domanda pandas 0.21.0 Problemi di compatibilità con il timestamp con matplotlib


Ho appena aggiornato i panda da 0.17.1 a 0.21.0 per sfruttare alcune nuove funzionalità e ho riscontrato problemi di compatibilità con matplotlib (che ho anche aggiornato all'ultima versione 2.1.0). In particolare, l'oggetto Timestamp sembra essere cambiato in modo significativo.

Mi capita di avere un'altra macchina ancora in esecuzione le versioni precedenti di panda (0.17.1) / matplotlib (1.5.1) che ho usato per confrontare le differenze:

Entrambe le versioni mostrano il mio indice DataFrame dtype='datetime64[ns]

DatetimeIndex(['2017-03-13', '2017-03-14', ... '2017-11-17'], type='datetime64[ns]', name='dates', length=170, freq=None)

Ma quando si chiama type(df.index[0]), Dà 0.17.1 pandas.tslib.Timestamp e dà 0.21.0 pandas._libs.tslib.Timestamp.

Quando si traccia con df.index come asse x:

plt.plot(df.index, df['data'])

matplotlibs per default formatta le etichette dell'asse x come date per panda 0.17.1 ma non riesce a riconoscerlo per pandas 0.21.0 e dà semplicemente il numero grezzo 1.5e18 (epoca in nanosec).

Ho anche un cursore personalizzato che riporta la posizione cliccata sul grafico usando matplotlib.dates.DateFormatter sul valore x che non riesce per 0.21.0 con:

OverflowError: signed integer is greater than maximum

Vedo che nel debug il valore x riportato è intorno a 736500 (cioè il conteggio del giorno dall'anno 0) per 0,17,1 ma è intorno a 1,5e18 (cioè il tempo di epoca nanosec) per 0,21,0.

Sono sorpreso da questa interruzione di compatibilità tra matplotlib e panda in quanto sono ovviamente utilizzati insieme dalla maggior parte delle persone. Mi manca qualcosa nel modo in cui chiamo la funzione di trama sopra per le versioni più recenti?

Aggiornare come ho detto sopra, preferisco chiamare direttamente plot con un dato oggetto di assi ma solo per il gusto di farlo, ho provato a chiamare il metodo di stampa del DataFrame stesso df.plot(). Non appena questo è fatto, tutti i grafici successivi riconoscono correttamente il Timestamp all'interno della stessa sessione python. È come se fosse impostata una variabile di ambiente, perché posso ricaricare un altro DataFrame o creare un altro asse con subplots e no dove si trova il 1.5e18 mostrare. Questo puzza davvero come un bug come dice l'ultimo doc pandas panda:

The plot method on Series and DataFrame is just a simple wrapper around plt.plot()

Ma chiaramente fa qualcosa alla sessione Python in modo tale che i grafici successivi gestiscano correttamente l'indice Timestamp.

In effetti, semplicemente eseguendo l'esempio al link panda precedente:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))

A seconda che ts.plot() viene chiamato o meno, il seguente grafico o formatta correttamente l'asse x come date o meno:

plt.plot(ts.index,ts)
plt.show()

Una volta che un plot membro viene chiamato, successivamente chiama plt.plot sulla nuova serie o DataFrame verrà formattato automaticamente senza dover chiamare nuovamente il metodo di stampa membro.


11
2017-11-21 03:22


origine


risposte:


C'è un problema con pandas datetimes e matplotlib proveniente dalla recente versione di panda 0.21, che non registra più i suoi convertitori all'importazione. Una volta che si usano quei convertitori una volta (all'interno dei panda), verranno registrati e automaticamente utilizzati anche da matplotlib.

Una soluzione alternativa sarebbe registrarli manualmente,

import pandas.plotting._converter as pandacnv
pandacnv.register()

In ogni caso il problema è ben noto sia sul lato panda che sul lato matplotlib, quindi ci sarà un qualche tipo di correzione per le prossime versioni. Panda sta pensando leggere il registroin una versione in uscita. Quindi questo problema potrebbe esserci solo temporaneamente. Un'opzione è anche quella di ritornare a Pandas 0.20.x dove questo non dovrebbe accadere.

Aggiornamento: questo non è più un problema con le versioni correnti di matplotlib (2.2.2) / panda (0.23.1), e probabilmente molte di quelle che sono state rilasciate da circa dicembre 2017, quando questo è stato corretto.


9
2017-11-21 13:52



Dopo aver aperto un problema su pandas github, ho imparato che questo era davvero un noto problema tra panda e matplotlib riguardanti la registrazione automatica del convertitore di unità. In effetti è stato elencato su ciò che è nuovo pagina che non ero riuscito a vedere prima, insieme al modo corretto di registrare i convertitori:

from pandas.tseries import converter
converter.register() 

Ciò avviene anche la prima volta che un metodo di stampa membro viene chiamato su una serie o DataFrame che spiega ciò che ho osservato sopra.

Sembra che sia stato fatto con l'intenzione che matplotlib dovrebbe implementare un supporto di base per pandas datetime, ma in effetti un avviso di deprecazione di qualche tipo potrebbe essere utile per una tale interruzione. Tuttavia fino a quando matplotlib non implementa effettivamente tale supporto (o una sorta di meccanismo di registrazione pigro), praticamente metto sempre queste due righe all'importazione dei panda. Quindi non sono sicuro del motivo per cui i panda vorrebbero disabilitare la registrazione automatica all'importazione prima che le cose siano pronte sul lato matplotlib.


6
2017-11-22 01:57