2017-11-21 128 views
9

Właśnie zaktualizowałem pandy z wersji 0.17.1 do 0.21.0, aby skorzystać z niektórych nowych funkcji, i wystąpił problem z kompatybilnością z matplotlib (który również zaktualizowałem do najnowszej wersji 2.1.0) . W szczególności wydaje się, że obiekt znacznika czasu ulega znacznej zmianie.pandy 0.21.0 Problem zgodności timestamp z matplotlib

zdarza mi się mieć inne urządzenie nadal działa starsze wersje pand (0.17.1)/matplotlib (1.5.1), który kiedyś porównał różnice:

Obie wersje pokazać mój indeks DataFrame być dtype='datetime64[ns]

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

Ale kiedy dzwoni type(df.index[0]), 0.17.1 i 0.21.0 daje pandas.tslib.Timestamp daje pandas._libs.tslib.Timestamp.

Podczas drukowania z df.index jako Oś X:

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

matplotlibs według domyślnych formatów etykiet osi X jak dat dla pand 0.17.1 ale nie uznaje go za pand 0.21.0 i po prostu daje surowy numer 1.5e18 (czas epoki w nanoseku).

Mam też dostosowany kursor że raporty kliknięciu lokalizację na wykresie za pomocą matplotlib.dates.DateFormatter na wartości X, która nie do 0.21.0 z:

OverflowError: signed integer is greater than maximum 

widzę w debugowania zgłoszoną wartości X wynosi około 736500 (tj. liczba dni od roku 0) dla 0.17.1, ale wynosi około 1,5e18 (tj. czas epoki nanosekcji) dla 0,21.

Jestem zaskoczony tą przerwą kompatybilności pomiędzy matplotlib i pandami, ponieważ są one oczywiście używane przez większość ludzi. Czy brakuje mi czegoś, co nazywam powyższą funkcją fabuły dla nowszych wersji?

Aktualizacja jak już wspomniano wyżej, wolę bezpośrednio dzwoniąc plot o danej osi obiektu, ale tylko dla heck tego, próbowałem wywołanie metody fabuły DataFrame samego df.plot(). Jak tylko zostanie to zrobione, wszystkie kolejne wykresy poprawnie rozpoznają datownik w ramach tej samej sesji pythona. To tak, jakby ustawiono zmienną środowiskową, ponieważ mogę ponownie załadować inną ramkę DataFrame lub utworzyć kolejne osie z subplots i nie ma miejsca, gdzie pojawia się 1.5e18. To naprawdę pachnie jak robaka jako ostatni doc pandy mówi pandas:

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

Ale wyraźnie robi coś do sesji Pythona takie, że kolejne działki do czynienia z indeksem Timestamp prawidłowo.

W rzeczywistości, po prostu uruchamiając przykład w powyższych pand link:

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)) 

zależności czy ts.plot() nazywa, czy nie, po działce albo poprawnie formatuje oś x jako dat czy nie:

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

Po wywołaniu wykresu elementu, późniejsze wywołanie plt.plot w nowej serii lub w ramce DataFrame zostanie automatycznie sformatowane automatycznie bez potrzeby ponownego wywoływania metody wykresu elementu.

Odpowiedz

6

Istnieje issue with pandas datetimes and matplotlib pochodzący z najnowszej wersji pandy 0.21, która nie rejestruje już swoich konwerterów podczas importu. Kiedy raz użyjesz tych konwerterów (w pandach), zostaną one zarejestrowane i automatycznie użyte przez matplotlib.

Rozwiązaniem byłoby zarejestrować je ręcznie,

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

W każdym razie problem jest dobrze znany na obu pand i matplotlib boku, więc nie będzie jakiś fix dla następnych wydaniach. Pandy myślą o readding the register w nadchodzącym wydaniu. Więc ten problem może być tam tylko tymczasowo. Opcją jest również powrót do pandy 0.20.x tam, gdzie nie powinno to nastąpić.

+0

Masz rację, otrzymałem podobną odpowiedź w sprawie, którą otworzyłem na pithas github. Publikuję nieco bardziej oficjalną metodę ze strony pand, którą próbowałem pracować. –

+0

Czy wypróbowałeś tu również tę metodę? Czy możesz zgłosić, czy działa, czy nie (powinien teoretycznie, ale nie mogłem spróbować, a jeśli nie, to lepiej usunąć odpowiedź). – ImportanceOfBeingErnest

+0

Próbowałem i to też zadziałało - skończyło się na tym, że korzystałem z dwóch linii na stronie internetowej pand, ponieważ prawdopodobnie są one bardziej prawdopodobne w przyszłości. –

5

Po otwarciu issue na github pandy dowiedziałem się, że był to rzeczywiście znany issue między pandami a matplotlib dotyczący automatycznej rejestracji konwertera jednostek. W rzeczywistości został on wymieniony na co nowego page którego nie udało się zobaczyć wcześniej, wraz z właściwym sposobem zarejestrować konwertery:

from pandas.tseries import converter 
converter.register() 

Jest to również zrobić za pierwszym razem metoda członek działka jest nazywany w serialu lub DataFrame, która wyjaśnia, co zaobserwowałem powyżej.

Wygląda na to, że zrobiono to z myślą o tym, że matplotlib ma za zadanie wprowadzić pewne podstawowe wsparcie dla datetime pandy, ale w rzeczywistości może to być przydatne ostrzeżenie o takiej amunicji. Jednak dopóki matplotlib nie wdroży takiego wsparcia (lub jakiegoś leniwego mechanizmu rejestracyjnego), praktycznie zawsze umieszczam te dwie linie przy importowaniu pand. Nie wiem więc, dlaczego pandy chciałyby wyłączyć automatyczną rejestrację przy imporcie, zanim wszystko będzie gotowe na stronie matplotlib.