在Bokeh Area图的x轴上显示日期

时间:2017-06-03 15:42:29

标签: python bokeh

像我这样传递我的数据框可以显示情节,但是当我指定x以对应我的日期列时,不会显示情节。你能说出这里可能出现的问题吗?我尝试将我的日期列转换为stringdatetime和其他格式,但没有成功。

import pandas as pd
from bokeh.charts import output_file, Area, defaults
from bokeh.io import show, output_notebook
output_notebook()

xf = pd.DataFrame([{'Cat1': 112.04, 'Cat2': 0.0, 'REDUCED_DATE': '2011-12'},
 {'Cat1': 359.57449999999994, 'Cat2': 579.35, 'REDUCED_DATE': '2012-01'},
 {'Cat1': 376.99000000000007, 'Cat2': 552.64, 'REDUCED_DATE': '2012-02'},
 {'Cat1': 416.86000000000007, 'Cat2': 543.35, 'REDUCED_DATE': '2012-03'},
 {'Cat1': 320.5847000000001, 'Cat2': 543.35, 'REDUCED_DATE': '2012-04'},
 {'Cat1': 521.0349999999999, 'Cat2': 553.33, 'REDUCED_DATE': '2012-05'},
 {'Cat1': 330.84, 'Cat2': 667.94, 'REDUCED_DATE': '2012-06'}])

xf["Date"] =xf.REDUCED_DATE.astype(str)
area1 = Area(xf,y=["Cat1","Cat2"], title="Area chart", legend="top_left",
             xlabel="Date",ylabel="Amount",stack=True)

show(area1, notebook_handle=True)

enter image description here

将日期作为x列传递根本不显示任何数据:

xf["Date"] =xf.REDUCED_DATE.astype(str)
area1 = Area(xf, x="REDUCED_DATE", y=["Cat1","Cat2"], title="Area chart",
             legend="top_left",xlabel="Date",ylabel="Amount",stack=True)

show(area1, notebook_handle=True)

enter image description here

1 个答案:

答案 0 :(得分:1)

显然bokeh.charts.Area中存在错误,如果已确认,则应在enter image description here中进行报告。我正在使用散景版本0.12.4,并且有一个关于要用作xaxis刻度标签的字符串值的好奇心(在本示例中为REDUCED_DATE)。如果第三个值为'2'且第四个值以'3'(或4,5,... 9)开头,则区域图表显示确定,否则不显示区域图表(如问题所示):

import pandas as pd
from bokeh.charts import output_file, Area
from bokeh.io import show, output_notebook
output_notebook()

xf = pd.DataFrame([
     {'Cat1': 112.04, 'Cat2': 0.0, 'REDUCED_DATE': '2011-12'},
     {'Cat1': 359.57449999999994, 'Cat2': 579.35, 'REDUCED_DATE': '2012-01'},
     {'Cat1': 376.99000000000007, 'Cat2': 552.64, 'REDUCED_DATE': '2'},
     {'Cat1': 416.86000000000007, 'Cat2': 543.35, 'REDUCED_DATE': '3'},
     {'Cat1': 320.5847000000001, 'Cat2': 543.35, 'REDUCED_DATE': '2012-04'},
     {'Cat1': 521.0349999999999, 'Cat2': 553.33, 'REDUCED_DATE': '2012-05'},
     {'Cat1': 330.84, 'Cat2': 667.94, 'REDUCED_DATE': '2012-06'}
])

area1 = Area(xf, x="REDUCED_DATE", y=["Cat1","Cat2"], title="Area chart",
             legend="top_left",xlabel="Date",ylabel="Amount",stack=True)
show(area1, notebook_handle=True)

输出: enter image description here

对我有用的解决方法是使用bokeh.plotting.figure创建一个由x_range定义bokeh.models.FactorRange并添加patches字形的数字:

import pandas as pd
import bokeh.plotting
from bokeh.charts import output_file
from bokeh.io import show, output_notebook
output_notebook()

xf = pd.DataFrame([
     {'Cat1': 112.04, 'Cat2': 0.0, 'REDUCED_DATE': '2011-12'},
     {'Cat1': 359.57449999999994, 'Cat2': 579.35, 'REDUCED_DATE': '2012-01'},
     {'Cat1': 376.99000000000007, 'Cat2': 552.64, 'REDUCED_DATE': '2012-02'},
     {'Cat1': 416.86000000000007, 'Cat2': 543.35, 'REDUCED_DATE': '2012-03'},
     {'Cat1': 320.5847000000001, 'Cat2': 543.35, 'REDUCED_DATE': '2012-04'},
     {'Cat1': 521.0349999999999, 'Cat2': 553.33, 'REDUCED_DATE': '2012-05'},
     {'Cat1': 330.84, 'Cat2': 667.94, 'REDUCED_DATE': '2012-06'}
])

# getting the coordinates of the patches:
nvals = xf.shape[0]
accum = pd.np.zeros(nvals)
vals = []
for cat in ['Cat1','Cat2']:
    prev_accum = accum.copy()
    accum += xf[cat].get_values()
    vals += [pd.np.concatenate((prev_accum,accum[::-1]))]

p = bokeh.plotting.figure(
        x_range=bokeh.models.FactorRange(factors=list(xf["REDUCED_DATE"]),offset=-1))
p.patches(xs=[range(nvals)+range(nvals-1,-1,-1)], ys=[vals[0]],
                color=['#f22c40'],alpha=0.8 ,legend='Cat1')
p.patches(xs=[range(nvals)+range(nvals-1,-1,-1)], ys=[vals[1]],
                color=['#5ab738'],alpha=0.8 ,legend='Cat2')
p.xaxis.major_label_orientation = 3.4142/4
p.legend[0].location = 'top_left'
p.xaxis.axis_label = "Date"
p.yaxis.axis_label = "Amount"
show(p)

这里的输出是正确的:

brewer.py

UPDATE散景版0.12.16

在最新版本的散景中offset不再支持

FactorRange。在以下代码中(在版本0.12.16中测试)我使用datetime作为x轴值。同样受以下代码启发:github issue #6376和{{3}}:

import pandas as pd
import bokeh.plotting
from bokeh.io import show, output_notebook

xf = pd.DataFrame([
     {'Cat1': 112.04, 'Cat2': 0.0, 'REDUCED_DATE': '2011-12'},
     {'Cat1': 359.57449999999994, 'Cat2': 579.35, 'REDUCED_DATE': '2012-01'},
     {'Cat1': 376.99000000000007, 'Cat2': 552.64, 'REDUCED_DATE': '2012-02'},
     {'Cat1': 416.86000000000007, 'Cat2': 543.35, 'REDUCED_DATE': '2012-03'},
     {'Cat1': 320.5847000000001, 'Cat2': 543.35, 'REDUCED_DATE': '2012-04'},
     {'Cat1': 521.0349999999999, 'Cat2': 553.33, 'REDUCED_DATE': '2012-05'},
     {'Cat1': 330.84, 'Cat2': 667.94, 'REDUCED_DATE': '2012-06'}
])

def stacked(df,N=2):
    df_top = df.iloc[:,0:N].cumsum(axis=1) # accumulates first N columns
    df_bottom = df_top.shift(axis=1).fillna({'Cat1': 0})[::-1]
    df_stack = pd.concat([df_bottom, df_top], ignore_index=True)
    return df_stack

dates  = [pd.datetime.strptime(x,'%Y-%m') for x in xf['REDUCED_DATE']]
x2 = np.hstack((dates[::-1], dates))
areas = stacked(xf)

source = bokeh.models.ColumnDataSource(dict(
    xs=[x2] * areas.shape[1],
    ys=[areas[c].values for c in areas],
    color=['#f22c40','#5ab738'],
    label=['Cat1','Cat2']
))

p = bokeh.plotting.figure( x_axis_type='datetime')
p.patches( xs='xs', ys='ys', color='color', legend='label', source=source,alpha=0.8)
p.xaxis.formatter = bokeh.models.formatters.DatetimeTickFormatter(months=["%Y-%m"])
p.xaxis.major_label_orientation = 3.4142/4
p.legend.location = 'top_left'
p.xaxis.axis_label = "Date"
p.yaxis.axis_label = "Amount"

output_notebook()
show(p)