我正在尝试将DateRangeSlider Widget实现到我的bokeh项目中。我正在使用小部件来调整我在csv文件中累积的范围内存在的股票日期数量。每当我移动滑块小部件时
我假设使用的数据类型不正确。问题在于我的更新功能。
我该如何解决这个问题?
from math import pi
import pandas as pd
import numpy as np
import datetime
import time
from datetime import date
from bokeh.layouts import row, widgetbox, column
from bokeh.models import ColumnDataSource, PrintfTickFormatter, CDSView,BooleanFilter
from bokeh.models.widgets import PreText, Select, DateRangeSlider, Button, DataTable, TableColumn, NumberFormatter
from bokeh.io import curdoc, show, reset_output
from bokeh.plotting import figure, output_file
DEFAULT_TICKERS = ['AAPL','GOOG','NFLX', 'TSLA']
ticker1 = Select(value='AAPL', options = DEFAULT_TICKERS)
range_slider1 = DateRangeSlider(start=date(2014,1,1) , end=date(2017,1,1), value=(date(2014,2,1),date(2016,3,1)), step=1)
def load_ticker(ticker):
fname = ( '%s.csv' % ticker.lower())
data = pd.read_csv( fname, header = None, parse_dates = ['Date'],
names =['Date','Open','High','Low','Close','AdjClose','Volume'])
return data
def get_data(t1):
data = load_ticker(t1)
return data
def ticker1_change(attrname, old, new):
update()
def range_slider_change(attrname, old, new):
update()
def update(selected=None):
t1 = ticker1.value
sd = str(range_slider1.value[0])
ed = str(range_slider1.value[1])
start_date = sd
end_date = ed
datarange = get_data(t1)
datarange['Date'] = pd.to_datetime(datarange['Date'])
mask = (datarange['Date'] > start_date) & (datarange['Date'] <= end_date)
data = datarange.loc[mask]
source.data = source.from_df(data)
p.title.text = t1
data = get_data(ticker1.value)
source = ColumnDataSource(data)
p = figure(plot_width=900, plot_height=400, x_axis_type='datetime')
p.grid.grid_line_alpha = 0.3
p.line('Date', 'Close', source=source)
ticker1.on_change('value', ticker1_change)
range_slider1.on_change('value', range_slider_change)
update()
layout = column(ticker1,range_slider1, p)
curdoc().add_root(layout)
curdoc().title = "Stock"
您正在将start_date
和end_date
转换为字符串:
sd = str(range_slider1.value[0])
ed = str(range_slider1.value[1])
start_date = sd
end_date = ed
然后在需要TimeStamp
的地方使用它们:
mask = (datarange['Date'] > start_date) & (datarange['Date'] <= end_date)
这正是“无法将字符串转换为时间戳”的消息正在告诉您。
您需要将滑块值转换为真正的TimeStamp
对象。有一个轻微的皱纹,滑块值可以是date
或int
(您可能最初将其设置为日期,但至少从Bokeh 0.13开始,它总是作为数字时间戳返回,具体而言,是自之后的毫秒数你需要处理这两种情况,这是一种方式:
if isinstance(range_slider1.value[0], (int, float)):
# pandas expects nanoseconds since epoch
start_date = pd.Timestamp(float(range_slider1.value[0])*1e6)
end_date = pd.Timestamp(float(range_slider1.value[1])*1e6)
else:
start_date = pd.Timestamp(range_slider1.value[0])
end_date = pd.Timestamp(range_slider1.value[1])
这种不一致的行为被认为是未来版本中要修复的错误。您可以在此处关注此问题以获取更多详细信息:https://github.com/bokeh/bokeh/issues/8015