2017-02-17 32 views
1

Я хотел бы задать диапазон оси datetime с помощью кнопки. Однако командаPython, Bokeh: Как изменить диапазон оси даты и времени

f.x_range = Range1d(start=start_date, end=end_date) 

не работает. При нажатии кнопки ничего не происходит. Я не получаю никаких ошибок, ни в терминальных окнах, которые запускают сервер Bokeh, ни на консольном выходе моего браузера Chrome.

Здесь вы найдете весь код. Я благодарен за любой совет.

Спасибо,

Джулиан

# Import libraries 
from bokeh.io import curdoc 
from bokeh.models import ColumnDataSource, DatetimeTickFormatter, Select, Range1d 
from bokeh.models.widgets import Button 
from bokeh.layouts import layout 
from bokeh.plotting import figure 
from datetime import datetime, timedelta 
from math import radians 


# Create figure 
f=figure(x_axis_type='datetime') 

# Create sample datetime data 
date_time = [datetime(2017,1,1) + timedelta(days=x) for x in range(0,365)] 

# Create ColumnDataSource 
source = ColumnDataSource(dict(datetime=date_time,parameter=range(0,365))) 

# Create Line 
f.line(x='datetime',y='parameter',color='olive',line_color='black',source=source) 

# Update xaxis function 
def update_xaxis(): 
    start_date = datetime(year=int(select_start_year.value), month=int(select_start_month.value), day=int(select_start_day.value)) 
    end_date = datetime(year=int(select_end_year.value), month=int(select_end_month.value), day=int(select_end_day.value))  
    f.x_range = Range1d(start=start_date, end=end_date) 

# Set date format for x axis 
f.xaxis.formatter=DatetimeTickFormatter(formats=dict(
    seconds=["%Y-%m-%d %H:%M:%S"], 
    minsec=["%Y-%m-%d %H:%M:%S"], 
    minutes=["%Y-%m-%d %H:%M:%S"], 
    hourmin=["%Y-%m-%d %H:%M:%S"], 
    hours=["%Y-%m-%d %H:%M:%S"], 
    days=["%Y-%m-%d %H:%M:%S"], 
    months=["%Y-%m-%d %H:%M:%S"], 
    years=["%Y-%m-%d %H:%M:%S"], 
    )) 
f.xaxis.major_label_orientation=radians(90) 

# Create Select and Button widgets 
options=[("2015","2015"),("2016","2016"),("2017","2017")] 
select_start_year=Select(title="Start Year",value="2017",options=options) 
options=[("01","01"),("02","02"),("03","03"),("04","04"),("05","05"),("06","06"),("07","07"),("08","08"),("09","09"),("10","10"),("11","11"),("12","12")] 
select_start_month=Select(title="Start Month",value="01",options=options) 
options=[("01","01"),("02","02"),("03","03"),("04","04"),("05","05"),("06","06"),("07","07"),("08","08"),("09","09"),("10","10"),("11","11"),("12","12"),("13","13"),("14","14"),("15","15"),("16","16"),("17","17"),("18","18"),("19","19"),("20","20"),("21","21"),("22","22"),("23","23"),("24","25"),("25","26"),("27","27"),("28","28"),("29","29"),("30","30"),("31","31")] 
select_start_day=Select(title="Start Day",value="01",options=options) 
options=[("2015","2015"),("2016","2016"),("2017","2017")] 
select_end_year=Select(title="End Year",value="2017",options=options) 
options=[("01","01"),("02","02"),("03","03"),("04","04"),("05","05"),("06","06"),("07","07"),("08","08"),("09","09"),("10","10"),("11","11"),("12","12")] 
select_end_month=Select(title="End Month",value="06",options=options) 
options=[("01","01"),("02","02"),("03","03"),("04","04"),("05","05"),("06","06"),("07","07"),("08","08"),("09","09"),("10","10"),("11","11"),("12","12"),("13","13"),("14","14"),("15","15"),("16","16"),("17","17"),("18","18"),("19","19"),("20","20"),("21","21"),("22","22"),("23","23"),("24","25"),("25","26"),("27","27"),("28","28"),("29","29"),("30","30"),("31","31")] 
select_end_day=Select(title="End Day",value="01",options=options) 
button = Button(label='Set Date') 

# Update x axis range on click 
button.on_click(update_xaxis) 

# Add elements to curdoc 
lay_out=layout([[f],[select_start_year],[select_start_month],[select_start_day],[select_end_year],[select_end_month],[select_end_day],[button]]) 
curdoc().add_root(lay_out) 

ответ

2

я понял, решение. Прежде всего, я использовал виджет Datepicker, который намного элегантнее, чем три виджета Select. Затем вам нужно преобразовать значение datetime из DatePicker в значение float/integer, которое представляет прошедшие секунды w.r.t. контрольная дата, т. е. 1 января 1970 года. Unix вычисляет это в секундах, Java Script нуждается в этом значении в миллисекундах, следовательно умножение на 1000. Вот код:

# Import libraries 
from bokeh.io import curdoc 
from bokeh.models import ColumnDataSource, DatetimeTickFormatter, DatePicker 
from bokeh.models.widgets import Button 
from bokeh.layouts import layout, column, row 
from bokeh.plotting import figure 
from datetime import datetime, timedelta 
from math import radians 


# Create figure 
f=figure(x_axis_type='datetime') 

# Create sample datetime data 
date_time = [datetime(2017,1,1) + timedelta(days=x) for x in range(0,365)] 

# Create ColumnDataSource 
source = ColumnDataSource(dict(datetime=date_time,parameter=range(0,365))) 

# Create Line 
f.line(x='datetime',y='parameter',color='olive',line_color='black',source=source) 

# Update xaxis function 
def update_xaxis(): 
    # Calculate time delta from reference time in seconds 
    timestamp_start = (datetime.combine(datepicker_start.value, datetime.min.time()) 
         - datetime(1970, 1, 1))/timedelta(seconds=1) 
    timestamp_end = (datetime.combine(datepicker_end.value, datetime.min.time()) 
         - datetime(1970, 1, 1))/timedelta(seconds=1) 
    f.x_range.start = int(timestamp_start)*1e3 # Multiply by 1e3 as JS timestamp is in milliseconds 
    f.x_range.end = int(timestamp_end)*1e3 # Multiply by 1e3 as JS timestamp is in milliseconds 

# Set date format for x axis 
f.xaxis.formatter=DatetimeTickFormatter(formats=dict(
    seconds=["%Y-%m-%d %H:%M:%S"], 
    minsec=["%Y-%m-%d %H:%M:%S"], 
    minutes=["%Y-%m-%d %H:%M:%S"], 
    hourmin=["%Y-%m-%d %H:%M:%S"], 
    hours=["%Y-%m-%d %H:%M:%S"], 
    days=["%Y-%m-%d %H:%M:%S"], 
    months=["%Y-%m-%d %H:%M:%S"], 
    years=["%Y-%m-%d %H:%M:%S"], 
    )) 
f.xaxis.major_label_orientation=radians(90) 

# Create Datepicker and Button widgets 
datepicker_start = DatePicker(title='Start Date') 
datepicker_end = DatePicker(title='End Date') 
button = Button(label='Set Date') 

# Update x axis range on click 
button.on_click(update_xaxis) 

# Add elements to curdoc 
lay_out=layout([[row(f, 
        column(button, 
          row(datepicker_start,datepicker_end)))]]) 
curdoc().add_root(lay_out)