Search code examples
datetimebokeh

Datetime axis in Bokeh


for my figure I wanted to use the 'datetime' option in bokeh as following:

top = figure(width=900, height=500, x_axis_type='datetime')

My data for the x-axis is in the datetime.time format.

x_time = [datetime.time(0, 0), datetime.time(0, 0, 3), datetime.time(0, 0, 13), datetime.time(0, 0, 23), datetime.time(0, 0, 26)]

However it produces the following error when trying to add:

top.image_url(x=datetime.time(0,0,3), y= 10 url = [some_url]]

and

top.add_layout(Arrow(x_start=datetime.time(0,0,0), y_start=5,
            x_end=datetime.time(0,0,3), y_end=10)


ValueError: expected an element of either String, Dict(String, Either(String, Instance(Transform), Instance(ColorMapper), Float)) or Float, got datetime.time(0, 0)

As suggested from Rutger Kassies I transformed my data to microseconds, now it only shows seconds: Change from seconds to minutes


Solution

  • It seems the Bokeh annotations only take numbers, not Datetime or Time objects. A workaround is to convert your times to microseconds and use those to plot.

    An example:

    from bokeh.plotting import figure, show, output_notebook
    from bokeh.models import Arrow
    import datetime
    
    def time_to_microseconds(t):
        dmin = datetime.datetime.min
        dummy_tdelta = (datetime.datetime.combine(dmin, t) - dmin)
        return dummy_tdelta.total_seconds()*1000
    
    x_time = [datetime.time(0,0,1),
              datetime.time(0,0,2),
              datetime.time(0,0,3),
              datetime.time(0,0,4),
              datetime.time(0,0,5)]
    
    top = figure(width=300, height=300, x_axis_type='datetime')
    
    # a line works fine with time objects
    top.line(x_time, range(len(x_time)))
    
    # layout needs numbers
    top.add_layout(Arrow(x_start=time_to_microseconds(datetime.time(0,0,2)), 
                         y_start=3,
                         x_end=time_to_microseconds(datetime.time(0,0,3)), 
                         y_end=2))
    

    enter image description here

    edit:

    You can change the tick-formatting with:

    from bokeh.models import DatetimeTickFormatter
    
    top.xaxis.formatter = DatetimeTickFormatter(seconds=["%M:%S"],
                                                minutes=["%M:%S"],
                                                minsec=["%M:%S"],
                                                hours=["%M:%S"])