I have a problem with the color of the legend dots. All of them are red while it should switch from red to green in 7.
The code that produces the last image is:
from bokeh.models import ColumnDataSource, Label, LabelSet, Range1d, Legend
from bokeh.plotting import figure, output_file, show
from bokeh.models import HoverTool
df = pd.DataFrame({'pc1': range(11),
'pc2': range(10,-1,-1),
'Muestra': ['A']*6+['B']*5,
'color':['#cf0c0c']*6+['#0dab51']*5},
index=range(1,12))
ID = ['{} {}'.format(i+1,j) for i,j in enumerate(df.Muestra)]
source = ColumnDataSource(data=dict(pc1=df.pc1,
pc2=df.pc2,
color=df.color,
ID=ID,
names=df.index))
p = figure(title='Principal Component Analysis')
p.scatter(x='pc1', y='pc2', size=15, fill_color='color', fill_alpha=0.6, line_color=None, source=source)
labels = LabelSet(x='pc1', y='pc2', text='names',
x_offset=5, y_offset=5, source=source, render_mode='canvas')
legend=Legend(items=[(ID[i-1],[p.renderers[0]]) for i in df.index])
p.add_layout(legend,'right')
p.add_layout(labels)
show(p)
I think it should be a renderers property but I am not sure.
Instead of manually creating the legend, you can also specify "ID" to be the legend_field
of the scatter renderer. This will automatically generate a legend for you where each entry corresponds to each unique value in the "ID" column:
import pandas as pd
from bokeh.models import ColumnDataSource, Label, LabelSet, Range1d, Legend
from bokeh.plotting import figure, output_file, show
from bokeh.models import HoverTool
df = pd.DataFrame(
{
"pc1": range(11),
"pc2": range(10, -1, -1),
"Muestra": ["A"] * 6 + ["B"] * 5,
"color": ["#cf0c0c"] * 6 + ["#0dab51"] * 5,
},
index=range(1, 12),
)
ID = ["{} {}".format(i + 1, j) for i, j in enumerate(df.Muestra)]
source = ColumnDataSource(
data=dict(pc1=df.pc1, pc2=df.pc2, color=df.color, ID=ID, names=df.index)
)
p = figure(title="Principal Component Analysis")
p.scatter(
x="pc1",
y="pc2",
size=15,
fill_color="color",
fill_alpha=0.6,
line_color=None,
source=source,
legend_field="ID" # New kwarg added here
)
labels = LabelSet(
x="pc1",
y="pc2",
text="names",
x_offset=5,
y_offset=5,
source=source,
render_mode="canvas",
)
# Removed these 2 lines
# legend=Legend(items=[(ID[i-1],[p.renderers[0]]) for i in df.index])
# p.add_layout(legend,'right')
p.add_layout(labels)
show(p)