I have been trying to create a line chart that represents 'values' as y axis and 'time' as x axis. I have successfully done so.
However, when there's a large time gap between values, there exist lines connected two dots from those values which create an ugly looking scenario.
Therefore, I would like to get rid of those lines.
Here's my runnable code:
# Import Library
import random
import pandas as pd
from bokeh.core.properties import value
from bokeh.io import show, output_notebook, export_png
from bokeh.plotting import figure, output_file
from bokeh.models import ColumnDataSource, Legend, HoverTool, layouts, CustomJS, Select, Circle, RangeTool
from bokeh.layouts import column
output_notebook() # Render inline in a Jupyter Notebook
# Create Line Chart
def create_line_chart_bokeh():
# Set data
dates = ['24-11-2017', '28-11-2017', '29-11-2017',
'23-03-2018', '27-03-2018', '12-08-2018']
dates = list(map(lambda i: pd.Timestamp(i), dates))
values = [random.randrange(101) for _ in range(len(dates))]
source = ColumnDataSource(data=dict(date=dates, close=values))
# Set Hover
TOOLTIPS = [
("Average Score", "@close")
]
# Set plot
p = figure(plot_height=300, plot_width=800, tools="xpan", toolbar_location=None,
tooltips=TOOLTIPS, x_axis_type="datetime", x_axis_location="above",
background_fill_color="white", x_range=(dates[0], dates[int(len(dates)-1)]), title='Test Line Chart')
# Set Line and Circle colours
line_colour = '#59819a'
circle_colour = '#ef5b45'
p.line('date', 'close', source=source, color=line_colour)
p.circle('date', 'close', source=source, color=circle_colour, size=4)
p.yaxis.axis_label = 'Scores' # set y axis label
# Set Time Selection Box
select = figure(title="Drag the middle and edges of the selection box to change the range above",
plot_height=130, plot_width=800, y_range=p.y_range,
x_axis_type="datetime", y_axis_type=None,
tools="", toolbar_location=None, background_fill_color="#efefef")
range_tool = RangeTool(x_range=p.x_range)
range_tool.overlay.fill_color = 'navy'
range_tool.overlay.fill_alpha = 0.2
select.line('date', 'close', source=source, color=line_colour)
select.ygrid.grid_line_color = None
select.add_tools(range_tool)
select.toolbar.active_multi = range_tool
# Show the result
show(column(p, select))
return None
# Call Function
create_line_chart_bokeh()
As can be seen above, those circled areas are not wanted. Is there anyone who has experiences or ideas to solve this problem?
This is a draft for what I want to achieve. I am thinking a time gap for deleting lines can be adjustable, or fixed as 2-or-3 month gap.
Thank you in advance,
Update!!
According to the answer below, the line now looks proper. However, there'a slight problem on hovering line itself. Hovering on circles work perfectly fine.
# Import Library
import random
import pandas as pd
from bokeh.core.properties import value
from bokeh.io import show, export_png, output_notebook
from bokeh.plotting import figure, output_file
from bokeh.models import ColumnDataSource, Legend, HoverTool, layouts, CustomJS, Select, Circle, RangeTool
from bokeh.layouts import column
from datetime import date
output_notebook() # Render inline in a Jupyter Notebook
# Create Line Chart
def create_line_chart_bokeh():
# Set data
dates = ['24-11-2017', '28-11-2017', '29-11-2017',
'23-03-2018', '27-03-2018', '12-08-2018']
dates = list(map(lambda i: pd.Timestamp(i), dates))
values = [random.randrange(101) for _ in range(len(dates))]
source = ColumnDataSource(data=dict(date=dates, close=values))
# Set Hover
TOOLTIPS = [
("Average Score", "@close")
]
# Set plot
p = figure(plot_height=300, plot_width=800, tools="xpan", toolbar_location=None,
tooltips=TOOLTIPS, x_axis_type="datetime", x_axis_location="above",
background_fill_color="white", x_range=(dates[0], dates[int(len(dates)-1)]), title='Test Line Chart')
# Set Line and Circle colours
line_colour = '#59819a'
circle_colour = '#ef5b45'
for i in range(len(dates)):
try:
diff = dates[i+1] - dates[i] #Compute difference between dates in days
if diff.days < 30:
p.line([dates[i], dates[i+1]], [values[i], values[i+1]], color=line_colour) #Only plot a line if difference in days < 30
except IndexError:
pass
p.circle('date', 'close', source=source, color=circle_colour, size=4)
p.yaxis.axis_label = 'Scores' # set y axis label
# Set Time Selection Box
select = figure(title="Drag the middle and edges of the selection box to change the range above",
plot_height=130, plot_width=800, y_range=p.y_range,
x_axis_type="datetime", y_axis_type=None,
tools="", toolbar_location=None, background_fill_color="#efefef")
range_tool = RangeTool(x_range=p.x_range)
range_tool.overlay.fill_color = 'navy'
range_tool.overlay.fill_alpha = 0.2
for i in range(len(dates)):
try:
diff = dates[i+1] - dates[i] #Compute difference between dates in days
if diff.days < 30:
select.line([dates[i], dates[i+1]], [values[i], values[i+1]], color=line_colour) #Only plot a line if difference in days < 30
except IndexError:
pass
select.ygrid.grid_line_color = None
select.add_tools(range_tool)
select.toolbar.active_multi = range_tool
# Show the result
show(column(p, select))
return None
# Call Function
create_line_chart_bokeh()
Hovering on Circles
Hovering on the Line
Solved!!
Based on the code below, I am now able to accomplish all the requirements. I took some pieces of the code and modified it further for my project.
# Import Library
import random
import pandas as pd
from bokeh.core.properties import value
from bokeh.io import show, export_png, output_notebook
from bokeh.plotting import figure, output_file
from bokeh.models import ColumnDataSource, Legend, HoverTool, layouts, CustomJS, Select, Circle, RangeTool
from bokeh.layouts import column
from datetime import date
output_notebook() # Render inline in a Jupyter Notebook
# Create Line Chart
def create_line_chart_bokeh():
# Set data
dates = ['24-11-2017', '28-11-2017', '29-11-2017',
'23-03-2018', '27-03-2018', '12-08-2018']
dates = list(map(lambda i: pd.Timestamp(i), dates))
values = [random.randrange(101) for _ in range(len(dates))]
source = ColumnDataSource(data=dict(date=dates, close=values))
# Set plot
p = figure(plot_height=300, plot_width=800, tools="xpan", toolbar_location="right",
x_axis_type="datetime", x_axis_location="above",
background_fill_color="white", x_range=(dates[0], dates[int(len(dates)-1)]), title='Test Line Chart')
# Set Line and Circle colours
line_colour = '#59819a'
circle_colour = '#ef5b45'
lineSource = {'date': [], 'close': []}
date, close = [], []
for i in range(len(dates)):
try:
diff = dates[i+1] - dates[i]
if diff.days < 30:
date.extend([dates[i], dates[i+1]])
close.extend([values[i], values[i+1]])
else:
lineSource['date'].append(date)
lineSource['close'].append(close)
date, close = [], []
except IndexError:
pass
lines = p.multi_line(xs='date', ys='close', source=ColumnDataSource(lineSource), color=line_colour)
circles = p.circle('date', 'close', source=source, color=circle_colour, size=4)
p.yaxis.axis_label = 'Scores' # set y axis label
hoverCircles = HoverTool(renderers=[circles], tooltips=[("Average Score", "@close")])
p.add_tools(hoverCircles)
hoverLines = HoverTool(renderers=[lines], tooltips=[("Average Score", "$y")])
p.add_tools(hoverLines)
# Set Time Selection Box
select = figure(title="Drag the middle and edges of the selection box to change the range above",
plot_height=130, plot_width=800, y_range=p.y_range,
x_axis_type="datetime", y_axis_type=None,
tools="", toolbar_location=None, background_fill_color="#efefef")
range_tool = RangeTool(x_range=p.x_range)
range_tool.overlay.fill_color = 'navy'
range_tool.overlay.fill_alpha = 0.2
select.line('date', 'close', source=source, color=line_colour)
select.ygrid.grid_line_color = None
select.add_tools(range_tool)
select.toolbar.active_multi = range_tool
# Show the result
show(column(p, select))
return None
# Call Function
create_line_chart_bokeh()
答案 0 :(得分:0)
只需用for循环绘制该行即可。每次检查日期之间的距离是否小于30天,如果是,则绘制线条。
import { HttpClient, HttpHeaders } from '@angular/common/http';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
this.http.post<any>
(`Your URL`, formData).subcribe(
(res) => {
console.log(res);
},
err => console.log(err)
);