The Goal: To generate a scatter plot from a pandas DataFrame with 3 columns: x, y, type (either a, b or c). The data points should have different colors based on the type. Every data point should have a hover effect. However, data points with type c should have a tap effect too. The data file (data_file.csv) looks something like:
x | y | z |
---|---|---|
1 | 4 | a |
2 | 3 | b |
3 | 2 | a |
4 | 4 | c |
.. | .. | .. |
My attempt: First, I imported the dataframe and divided into two parts: one with c type data and another with the everything else. Then I created two columndatasource and plotted the data. Is there a shortcut or better way than this? Also, I couldn't achieve some feature (see below).
Code:
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, OpenURL, TapTool
from bokeh.models.tools import HoverTool
from bokeh.transform import factor_cmap
file = "data.csv"
df = read_csv(file, skiprows=1, header=None, sep="\t")
# now I will seperate the dataframe into two: one with type **a** & **b**
# and another dataframe containing with type **c**
c_df = df.drop(df[df[2] != 'c'].index)
ab_df = df.drop(df[df[2] == 'c'].index)
ab_source = ColumnDataSource(data=dict(
Independent = ab_df[0],
Dependent = ab_df[1],
Type = ab_df[2]
))
c_source = ColumnDataSource(data=dict(
Independent = c_df[0],
Dependent = c_df[1],
Type = c_df[2],
link = "http://example.com/" + c_df[0].apply(str) + ".php"
))
p = figure(title="Random PLot")
p.circle('Independent', 'Dependent',
size=10,
source=ab_source,
color=factor_cmap('Type',
['red', 'blue'],
['a', 'b']),
legend_group='Type'
)
p.circle('Independent', 'Dependent',
size=12,
source=c_source,
color=factor_cmap('Type',
['green'],
['c']),
name='needsTapTool'
)
p.legend.title = "Type"
hover = HoverTool()
hover.tooltips = """
<div>
<h3>Type: @Type</h3>
<p> @Independent and @Dependent </p>
</div>
"""
p.add_tools(hover)
url = "@link"
tap = TapTool(names=['needsTapTool'])
tap.callback = OpenURL(url=url)
p.add_tools(tap)
show(p)
Problems: (1) How can I add two different hover tools so that different data points will behave differently depending on their type? Whenever I add another hover tool, only the last one is getting effective.
(2) How can I take part of a data in CDS? For example, imagine I have a column called 'href' which contains a link but have a "http://www" part. Now how can I set the 'link' variable inside a CDS that doesn't contain this part? when I try:
c_source = ColumnDataSource(data=dict(
link = c_df[3].apply(str)[10:]
))
I get a keyError. Any help will be appreciated.