使用Pandas数据框在Bokeh图中排序日期
我有一个pandas数据框,每天有4个不同的分数:
import pandas as pd
df = pd.DataFrame( {u'Date' : ['2014-08-15', '2014-08-16', '2014-08-17', '2014-08-18', '2014-08-19', '2014-08-20',
'2014-08-15', '2014-08-16', '2014-08-17', '2014-08-18', '2014-08-19', '2014-08-20',
'2014-08-15', '2014-08-16', '2014-08-17', '2014-08-18', '2014-08-19', '2014-08-20',
'2014-08-15', '2014-08-16', '2014-08-17', '2014-08-18', '2014-08-19', '2014-08-20'],
u'Score': [-0.13, -0.25, 0.1, -0.3, -0.1, 0.1,
-0.1, 0.1, -0.05, 0.2, -0.13, -0.25,
0.2, 0.5, 0.4, -0.2, -0.25, 0.1,
-0.3, 0.1, 0.25, 0.05, -0.05, 0.2]})
df.Date = pd.to_datetime(df.Date,format='%Y-%m-%d')
我想画出每天分数的平均值。我尝试了以下代码:
from numpy import *
from bokeh.plotting import *
output_file('question.html')
figure(x_axis_type="datetime", plot_width=800, plot_height=500)
grouped = df.groupby("Date")
score = grouped["Score"]
avg = score.mean()
print dates
dates = asarray(grouped.groups.keys())
hold(True)
line(dates, avg, line_color="grey", line_width=8, line_join="round")
asterisk(dates, avg, line_color="black", size=15)
hold(False)
但是,这段代码导致日期数组乱了:
print dates
['2014-08-15T02:00:00.000000000+0200' '2014-08-16T02:00:00.000000000+0200'
'2014-08-18T02:00:00.000000000+0200' '2014-08-19T02:00:00.000000000+0200'
'2014-08-17T02:00:00.000000000+0200' '2014-08-20T02:00:00.000000000+0200']
因此,我得到的图表线条(可以在这个链接查看图片)也是错误的。
我尝试用以下代码按日期排序:
df = df.sort(['Date'])
但这并没有帮助。
另一方面,如果我尝试画一个只有4天的数据框,而不是6天:
df = pd.DataFrame( {u'Date' : ['2014-08-15', '2014-08-16', '2014-08-17', '2014-08-18',
'2014-08-15', '2014-08-16', '2014-08-17', '2014-08-18',
'2014-08-15', '2014-08-16', '2014-08-17', '2014-08-18',
'2014-08-15', '2014-08-16', '2014-08-17', '2014-08-18'],
u'Score': [-0.13, -0.25, 0.1, -0.3,
-0.1, 0.1, -0.05, 0.2,
0.2, 0.5, 0.4, -0.2,
-0.3, 0.1, 0.25, 0.05]})
那么日期数组就会是有序的,图表也正确。我不明白为什么会这样,但无论如何,我想要的是包含6天或更多日期的图表。
如果你能帮我一下,我会非常感激。很明显,我在某些地方做错了,但我还是个初学者,已经尝试了无数种解决方案,但都没有成功。谢谢你!
2 个回答
0
这个 avg
序列会把时间戳按正确的顺序放在索引里,可以直接传给 bokeh 的绘图函数,像这样。
line(avg.index, avg, line_color="grey", line_width=8, line_join="round")
asterisk(avg.index, avg, line_color="black", size=15)
1
如果你检查一下类型:
>>> type(df.groupby('Date').groups)
<class 'dict'>
那么,作为一个字典,df.groupby('Date').groups
在你访问项目或键的时候,并没有提供任何顺序保证; 在你的例子中,grouped.groups.keys()
;所以当你单独从groupby
中提取dates
和avg
时,你会失去它们之间的一致性和对应关系。
如果你想处理datetime
对象和简单的numpy数组(而不是pandas系列),你可以按照下面的方式操作,以确保顺序一致:
>>> ts = df.groupby('Date')['Score'].mean()
>>> avg, dates = ts.values, ts.index.map(pd.Timestamp.date)
这样你就会得到:
>>> avg
array([-0.0825, 0.1125, 0.175 , -0.0625, -0.1325, 0.0375])
>>> dates
array([datetime.date(2014, 8, 15), datetime.date(2014, 8, 16), datetime.date(2014, 8, 17), datetime.date(2014, 8, 18),
datetime.date(2014, 8, 19), datetime.date(2014, 8, 20)], dtype=object)
注意,groupby
默认参数是sort=True
,所以输出已经按索引排序了:
>>> df.groupby('Date')['Score'].mean()
Date
2014-08-15 -0.082
2014-08-16 0.112
2014-08-17 0.175
2014-08-18 -0.062
2014-08-19 -0.133
2014-08-20 0.038
Name: Score, dtype: float64