2015-07-10 84 views
7

我有一个熊猫数据框,每个观察都有一个日期(作为datetime [64]格式的一列条目)。这些日期分布在大约5年的时间内。我想绘制所有观测日期的核密度图,以x轴标记年。如何绘制熊猫日期的核心密度图?

我想通了如何创建相对于某些基准日期时间增量,然后创建的每个观测和基准日期之间的小时/天/年数的密度图:

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

但是,这并不是我想要的:如果我转换为年份 - 三角洲,那么x轴是正确的,但我失去了年内的变化。但是如果我花时间或小时计算更小的时间单位,x轴标签就更难解释了。

在熊猫中进行这项工作最简单的方法是什么?

+0

看看KDE-情节seaborn:http://stanford.edu/~mwaskom/software/seaborn/generated/seaborn.kdeplot.html – Moritz

回答

3

通过@JohnE的回答启发,另一种方法来转换日期数值是使用.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

很好的回答。这比我的答案强大得多,因为它将正确处理闰年和1月1日以外的开始日期。我会将此推荐为接受的答案。 – JohnE

3

我想有一些更好的和自动的方式来做到这一点,但如果没有,那么这应该是一个体面的解决方法。首先,让我们建立了一些样本数据:

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 

正如你所看到的,“相对”仅仅是因为起始日天数。它本质上是一个整数,所以你真正需要做的就是相对于开始日期对它进行规范化。

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 

你需要稍微调整,对于日期没有启动一月1这也忽略任何闰年这实在不是一个实际的问题,如果你只是产生一个KDE情节超过5年,但取决于你可能想做什么,这可能很重要。

这里的情节

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

enter image description here