Python Bokeh基本分组vbar-简化x轴

时间:2018-07-13 16:45:58

标签: python plot bokeh

对于一些非常简单的数据,成组的vbar图的x轴杂乱无章,而且我找不到解决方法。

目的是在单个图上显示Twitter帐户的生命周期和最后90天的每小时发推数。

我已经有一个仅适用于生存期数据的工作版本,可以产生适当的简单/整洁的输出。

对于分组版本,我想显示一个像单版本一样的简单代码,并使用颜色图例指示列的数据标签。

from bokeh.io import show, output_file, export_png
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, FactorRange, Label, Title
from bokeh.transform import factor_cmap    

data = {'hours_active': {0: 11, 1: 0, 2: 0, 3: 0, 4: 0, 5: 2, 6: 15, 7: 27, 8: 75, 9: 96, 10: 205, 11: 278, 12: 241, 13: 238, 14: 236, 15: 184, 16: 232, 17: 164, 18: 211, 19: 236, 20: 197, 21: 199, 22: 253, 23: 97}, 'ninety_days_hours_active': {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 2, 6: 15, 7: 23, 8: 68, 9: 78, 10: 94, 11: 111, 12: 135, 13: 80, 14: 109, 15: 102, 16: 94, 17: 58, 18: 106, 19: 94, 20: 110, 21: 98, 22: 89, 23: 2}}

    hours = [str(i) for i in range(0, 24)]
    days =  ['all', '90']

    data = {'hours' : hours, 'all':list(data['hours_active'].values()), '90': list(data['ninety_days_hours_active'].values())}

    x = [ (str(hour), day) for hour in hours for day in days ]

    counts = sum(zip(data['all'], data['90']), ())

    colors = ['#ffff1a', '#191971']

    source = ColumnDataSource(data=dict(x=x, counts=counts))

    p = figure(x_range=FactorRange(*x), plot_width=500, plot_height=500, title="Tweets All/Last 90 Days", )

    p.toolbar_location = None
    p.xgrid.grid_line_color = None
    p.min_border = 40
    p.axis.axis_line_width = 2
    p.y_range.start = 0
    p.vbar(x='x', top='counts', width=0.9, source=source, fill_color=factor_cmap('x', palette=colors, factors=days, start=1, end=2))

    show(p)

Output from above code:

Example with suitable x-axis

我选择避免使用pandas / dataframes,因为我想尽量减少依赖项,并且因为这是另一个需要学习的软件包(我很傻,不是程序员);数据是在更大程序中使用的另一个词典的替代物。

但是,如果有一种更简洁的方法,我就不会被上述代码锁定。


更新

使用躲避的建议是正确的。 以下代码产生了我想要的几乎,但是将附件图像视为两件事并不能完全按照我的期望进行渲染。我还没有打扰过一个传奇。

from bokeh.io import show, output_file
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.transform import dodge

with open('dsd_dict') as d:
    ddict = json.load(d)

hours = [str(i) for i in range(0, 24)]  # 'fruits'

data = {'hours' : hours, 'all':list(ddict['hours_active'].values()), '90': list(ddict['ninety_days_hours_active'].values()), '30': list(ddict['thirty_days_hours_active'].values())}

colors = ['#ffff1a', '#338dff', '#191971', 'firebrick']

source = ColumnDataSource(data=data)

p = figure(x_range=hours, plot_width=600, plot_height=500, title="Tweets All/Last 90/30 Days",  toolbar_location=None, tools="")

p.xgrid.grid_line_color = None
p.xgrid.grid_line_color = None
p.min_border = 40
p.y_range.start = 0

# X-AXIS SETTINGS #
p.xaxis[0].formatter = PrintfTickFormatter(format="%'02s")
p.xaxis.axis_label = '24 Hour Clock - UTC/GMT'
p.xaxis.axis_label_standoff = 10
p.xaxis.axis_label_text_font = 'dejavu sans'
p.xaxis.axis_label_text_font_size = '8pt'
p.xaxis.axis_label_text_color = 'black'
p.xaxis.axis_label_text_font_style = 'bold'

r = p.vbar(x=dodge('hours', 0.0, range=p.x_range), top='all', width=0.33, source=source, color=colors[0])

glyph = r.glyph
glyph.line_color = "black"
glyph.line_dash = 'solid'
glyph.line_width = 0.1

p.vbar(x=dodge('hours', 0.33, range=p.x_range), top='90', width=0.33, source=source, color=colors[1])

p.vbar(x=dodge('hours', 0.66, range=p.x_range), top='30', width=0.33, source=source, color=colors[3])

show(p)

Output from updated code

如我们所见,RHS末端被压碎,没有完全显示出第三条,并且这些列没有足够垂直地位于x轴刻度线上。我希望它们位于刻度之间 之间,因此很明显值是(例如)0100-0200。

我猜我只是需要研究如何调整偏移量,但是任何进一步的指针都是最欢迎的

1 个答案:

答案 0 :(得分:0)

一种选择是旋转刻度线标签:

p.xaxis.major_label_orientation = "vertical" # or value in radians works too

但是听起来您根本不需要嵌套的层次结构轴。在这种情况下,应改用Visual Dodge,以使轴上只有一层标签。这是一个完整的示例:

from bokeh.core.properties import value
from bokeh.io import show, output_file
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.transform import dodge

fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ['2015', '2016', '2017']

data = {'fruits' : fruits,
        '2015'   : [2, 1, 4, 3, 2, 4],
        '2016'   : [5, 3, 3, 2, 4, 6],
        '2017'   : [3, 2, 4, 4, 5, 3]}

source = ColumnDataSource(data=data)

p = figure(x_range=fruits, y_range=(0, 10), plot_height=250, title="Fruit Counts by Year",
           toolbar_location=None, tools="")

p.vbar(x=dodge('fruits', -0.25, range=p.x_range), top='2015', width=0.2, source=source,
       color="#c9d9d3", legend=value("2015"))

p.vbar(x=dodge('fruits',  0.0,  range=p.x_range), top='2016', width=0.2, source=source,
       color="#718dbf", legend=value("2016"))

p.vbar(x=dodge('fruits',  0.25, range=p.x_range), top='2017', width=0.2, source=source,
       color="#e84d60", legend=value("2017"))

p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
p.legend.location = "top_left"
p.legend.orientation = "horizontal"

show(p)

enter image description here