2015-07-10 3 views
7

Ich habe einen Pandas-Datenrahmen, wo jede Beobachtung ein Datum hat (als eine Spalte von Einträgen im Format datetime [64]). Diese Daten sind über einen Zeitraum von ca. 5 Jahren verteilt. Ich möchte eine Kerndichte-Darstellung der Daten aller Beobachtungen zeichnen, wobei die Jahre auf der x-Achse stehen.Wie Plot der Kerndichte von Daten in Pandas?

Ich habe herausgefunden, wie eine Zeit-Delta relativ zu einem Bezugszeitpunkt erstellen und dann eine Dichte Diagramm der Anzahl der Stunden/Tage/Jahr zwischen jeder Beobachtung und dem Stichtag erstellen:

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

Aber das ist nicht genau das, was ich will: Wenn ich in Jahr-Deltas umwandel, dann ist die X-Achse richtig, aber ich verliere die Variation innerhalb eines Jahres. Aber wenn ich eine kleinere Zeiteinheit wie Stunde oder Tag verwende, sind die Beschriftungen der X-Achse viel schwieriger zu interpretieren.

Was ist der einfachste Weg, um dies in Pandas funktionieren zu lassen?

+0

Blick auf kde-Grundstück in Seaborn: http://stanford.edu/~mwaskom/software/seaborn/generated/seaborn.kdeplot.html – Moritz

Antwort

3

Inspiriert von @JohnE ‚s Antwort, ein alternativer Ansatz Datum numerischen Wert zu konvertieren ist .toordinal() zu verwenden.

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

Gute Antwort. Dies ist viel robuster als meine Antwort, da es Schaltjahre und Starttermine außer dem 1. Januar korrekt behandelt. Ich würde dies als die akzeptierte Antwort empfehlen. – JohnE

3

Ich stelle mir vor es gibt eine bessere und automatische Möglichkeit, dies zu tun, aber wenn nicht, dann sollte dies eine anständige Problemumgehung sein. Lassen Sie uns zunächst einige Beispieldaten ein:

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 

Wie Sie sehen können, ‚rel‘ ist nur die Anzahl der Tage seit dem Starttag. Es ist im Wesentlichen eine ganze Zahl, so dass Sie es nur in Bezug auf das Startdatum normalisieren müssen.

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 

Sie müssen, dass für ein Datum leicht anzupassen nicht 1. auf Jan beginnend auch alle Schaltjahre ist zu ignorieren, die wirklich kein praktisches Problem ist, wenn Sie nur ein KDE Grundstück von über 5 Jahre produzieren , aber es könnte wichtig sein, je nachdem, was Sie sonst noch tun möchten.

Hier ist das Grundstück

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

enter image description here