简体   繁体   中英

How to create a Bokeh DataTable DateTime formatter?

Bokeh provides bokeh.models.DateFormatter() to show the date in a column (see class DateFormatter(**kwargs) ). Is there a way to create a Formatter that also shows the time HH:MM:SS and possible also the milliseconds? When editing in the table(double click on a date) one can see the epoch milliseconds. I could create another column with another set of data having seconds of day and use class NumberFormatter(**kwargs) with format "00:00:00" and another column with the milliseconds, but I would not be able to edit those and have it reflected on the graph glyphs, unless somehow I make the seconds of day data continuosly linked to the datetime values (is there a way to do so?). So I hope there is a way to work on a Formatter to display time out of the datetime data in a bokeh DataTable.

from datetime import datetime
import bokeh, bokeh.plotting

data = dict(dates=[datetime(2016, 12, 2,15,30,0,123456),
                   datetime(2016, 12, 2,15,30,5,250500),
                   datetime(2016, 12, 2,15,30,10,756050)],
            altitude=[100.,150.,125.])

source = bokeh.models.ColumnDataSource(data)

columns = [bokeh.models.TableColumn(field="dates", title="Date",
           formatter=bokeh.models.DateFormatter()),
           bokeh.models.TableColumn(field="altitude", title="altitude")]

data_table = bokeh.models.DataTable(source=source, columns=columns,
                   row_headers=False,width=500, height=150, editable=True)

p = bokeh.plotting.figure(width=400,height=200,x_axis_type="datetime", 
                          background_fill_color="lightgray")
p.circle(x="dates",y="altitude",source=source, size=10)
bokeh.io.output_notebook()
bokeh.io.show(bokeh.io.gridplot([[p],[data_table]]))

在此输入图像描述

UPDATE

A workaround is to create another column with the time HH:MM:SS (no milliseconds though. For that @Julian solution will work best). But editing that value will not be reflected in the graph. Editing the date milliseconds does update the graph but will not update the time column. Probably there is a way to connect the time column with the date column with some custom CustomJS . I have to comment that there is a working progress feature in bokeh github: Updating dates in datatable that might help here a lot.

from datetime import datetime
import bokeh, bokeh.plotting

t1 = datetime(2016, 12, 2,15,30,0,123456)
t2 = datetime(2016, 12, 2,15,30,5,250500)
t3 = datetime(2016, 12, 2,15,30,10,756050)

data = dict(dates = [t1,t2,t3],
            times = [t1.hour*3600 + t1.minute*60 + t1.second,
                    t2.hour*3600 + t2.minute*60 + t2.second,
                    t3.hour*3600 + t3.minute*60 + t3.second],
            altitude=[100.,150.,125.])

source = bokeh.models.ColumnDataSource(data)

tfmt = bokeh.models.NumberFormatter(format="00:00:00")
datefmt = bokeh.models.DateFormatter(format="ddMyy")
hfmt = bokeh.models.NumberFormatter(format="0.00")
columns = [bokeh.models.TableColumn(field="dates", title="Date",formatter=datefmt),
           bokeh.models.TableColumn(field="times", title="time", formatter=tfmt, editor=None),
           bokeh.models.TableColumn(field="altitude", title="altitude (km)", formatter=hfmt)]

data_table = bokeh.models.DataTable(source=source, columns=columns,
                   row_headers=False,width=500, height=150, editable=True)

p = bokeh.plotting.figure(width=400,height=200,x_axis_type="datetime", 
                          background_fill_color="lightgray")
p.circle(x="dates",y="altitude",source=source, size=10)
bokeh.io.output_notebook()
bokeh.io.show(bokeh.io.gridplot([[p],[data_table]]))

在此输入图像描述

UPDATE 04/13/2018

Bokeh version 0.12.16dev allows for a DataTable to have a DateFormatter that supports time information:

bokeh.models.DateFormatter(format="%m/%d/%Y %H:%M:%S")

For all the possibilities see class DateFormatter(**kwargs) .

在此输入图像描述

One partial solution is to separate the data sources for table and plot. Then you can leave the x-data for the plot in datetime format, and transform the date data for the table into a string. Of cause, then edits in the table are not reflected in the plot. Maybe with a callback function you can link the two data sources.

from datetime import datetime
import bokeh, bokeh.plotting

datetime_dates=[datetime(2016, 12, 2,15,30,0,123456),
                   datetime(2016, 12, 2,15,30,5,250500),
                   datetime(2016, 12, 2,15,30,10,756050)]
string_dates = []
for i in datetime_dates: string_dates.append(i.strftime("%Y-%m-%d %H:%M:%S.%f"))

data_plt = dict(dates=datetime_dates,
                     altitude=[100.,150.,125.])
data_tbl = dict(dates=string_dates,
                     altitude=[100.,150.,125.])

source_plot  = bokeh.models.ColumnDataSource(data_plt)
source_table = bokeh.models.ColumnDataSource(data_tbl)

columns = [bokeh.models.TableColumn(field="dates", title="Date"),
           bokeh.models.TableColumn(field="altitude", title="altitude")]

data_table = bokeh.models.DataTable(source=source_table, columns=columns,
                   row_headers=False,width=500, height=150, editable=True)

p = bokeh.plotting.figure(width=400,height=200,x_axis_type="datetime", 
                          background_fill_color="lightgray")
p.circle(x="dates",y="altitude",source=source_plot, size=10)
bokeh.io.output_notebook()
bokeh.io.show(bokeh.io.gridplot([[p],[data_table]]))

enter image description here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM