2015-07-10 12 views
7

Mam pandasową ramkę danych, gdzie każda obserwacja ma datę (jako kolumna wpisów w formacie datetime [64]). Daty te są rozłożone na okres około 5 lat. Chciałbym wykreślić wykres gęstości splotów z datami wszystkich obserwacji, z latami oznaczonymi na osi X.Jak wykreślić wykres gęstości dat w pandach?

I zorientowali się, jak stworzyć względny czas-delta w pewnym dniu referencyjnym, a następnie utworzyć wykres gęstości liczbę godzin/dni/lata między każdej obserwacji i dacie odniesienia:

df['relativeDate'].astype('timedelta64[D]').plot(kind='kde') 

Ale nie jest to dokładnie to, czego chcę: jeśli przejdę na rok-delty, to oś X ma rację, ale tracę zmienność w ciągu roku. Ale jeśli biorę mniejszą jednostkę czasu, taką jak godzina czy dzień, etykiety osi X są trudniejsze do zinterpretowania.

Jaki jest najprostszy sposób na sprawdzenie tego w Pandach?

+0

spojrzenie na kde-plot w Seaborn: http://stanford.edu/~mwaskom/software/seaborn/generated/seaborn.kdeplot.html – Moritz

Odpowiedz

3

Zainspirowany odpowiedź @JohnE „s, alternatywne podejście do konwertowania daty do wartości liczbowej jest użycie .toordinal().

import pandas as pd 
import numpy as np 

# simulate some artificial data 
# =============================== 
np.random.seed(0) 
dates = pd.date_range('2010-01-01', periods=31, freq='D') 
df = pd.DataFrame(np.random.choice(dates,100), columns=['dates']) 
# use toordinal() to get datenum 
df['ordinal'] = [x.toordinal() for x in df.dates] 

print(df) 

     dates ordinal 
0 2010-01-13 733785 
1 2010-01-16 733788 
2 2010-01-22 733794 
3 2010-01-01 733773 
4 2010-01-04 733776 
5 2010-01-28 733800 
6 2010-01-04 733776 
7 2010-01-08 733780 
8 2010-01-10 733782 
9 2010-01-20 733792 
..  ...  ... 
90 2010-01-19 733791 
91 2010-01-28 733800 
92 2010-01-01 733773 
93 2010-01-15 733787 
94 2010-01-04 733776 
95 2010-01-22 733794 
96 2010-01-13 733785 
97 2010-01-26 733798 
98 2010-01-11 733783 
99 2010-01-21 733793 

[100 rows x 2 columns]  

# plot non-parametric kde on numeric datenum 
ax = df['ordinal'].plot(kind='kde') 
# rename the xticks with labels 
x_ticks = ax.get_xticks() 
ax.set_xticks(x_ticks[::2]) 
xlabels = [dt.datetime.fromordinal(int(x)).strftime('%Y-%m-%d') for x in x_ticks[::2]] 
ax.set_xticklabels(xlabels) 

enter image description here

+2

dobra odpowiedź. Jest to o wiele bardziej niezawodne niż moja odpowiedź, ponieważ będzie poprawnie obsługiwać lata przestępne i daty rozpoczęcia inne niż 1 stycznia. Polecam to jako zaakceptowaną odpowiedź. – JohnE

3

Wyobrażam sobie, że istnieje lepszy i automatyczny sposób, aby to zrobić, ale jeśli nie, to powinno to być przyzwoite obejście. Najpierw skonfigurować niektóre dane przykładowe:

np.random.seed(479) 
start_date = '2011-1-1' 
df = pd.DataFrame({ 'date':np.random.choice( 
        pd.date_range(start_date, periods=365*5, freq='D'), 50) }) 

df['rel'] = df['date'] - pd.to_datetime(start_date) 
df.rel = df.rel.astype('timedelta64[D]') 

     date rel 
0 2014-06-06 1252 
1 2011-10-26 298 
2 2013-08-24 966 
3 2014-09-25 1363 
4 2011-12-23 356 

Jak widać, „rel” jest tylko liczba dni od dnia startu. Jest to w zasadzie liczba całkowita, więc wszystko, co naprawdę musisz zrobić, to znormalizować ją w odniesieniu do daty początkowej.

df['year_as_float'] = pd.to_datetime(start_date).year + df.rel/365. 

     date rel year_as_float 
0 2014-06-06 1252 2014.430137 
1 2011-10-26 298 2011.816438 
2 2013-08-24 966 2013.646575 
3 2014-09-25 1363 2014.734247 
4 2011-12-23 356 2011.975342 

trzeba by dostosować że lekko na randkę nie wychodząc sty 1. To też ignorowania lata przestępne, które naprawdę nie jest praktycznym problemem, jeśli jesteś po prostu tworząc fabułę KDE ponad 5 lat , ale może to mieć znaczenie w zależności od tego, co jeszcze chcesz zrobić.

Oto fabuła

df['year_as_float']d.plot(kind='kde') 

enter image description here

Powiązane problemy