I have an evident problem with the legend of the following plot:
I understand the issue, python is evaluating '2A' > '10 B' as True, but I dont know how to walkaround it (maybe using natsort package?). I would like to emphasize that the reordering process has to be automatic since I dont know how many samples I will have in the future. The code is here:
from bokeh.models import ColumnDataSource, Label, LabelSet, Range1d
from bokeh.plotting import figure, output_file, show
from bokeh.models import HoverTool
import pandas as pd
df = pd.DataFrame(
{
"pc1": range(11),
"pc2": range(10, -1, -1),
"Muestra": ["A"] * 6 + ["B"] * 5,
"color": ["#cf0c0c"] * 6 + ["#0dab51"] * 5,
},
index=range(11),
)
ID = ["{} {}".format(i + 1, j) for i, j in enumerate(df.Muestra)]
# Tools
TOOLS = "hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select"
source = ColumnDataSource(
data=dict(pc1=df.pc1, pc2=df.pc2, color=df.color, ID=ID, names=df.index)
)
x_min, x_max = (
min(df.pc1) - abs(min(df.pc1)) * 0.1,
max(df.pc1) + abs(max(df.pc1)) * 0.1,
)
y_min, y_max = (
min(df.pc2) - abs(min(df.pc2)) * 0.1,
max(df.pc2) + abs(max(df.pc2)) * 0.1,
)
p = figure(
title="Principal Component Analysis",
x_range=Range1d(x_min, x_max),
y_range=Range1d(y_min, y_max),
tools=TOOLS,
height=650,
width=1000,
)
p.scatter(
x="pc1",
y="pc2",
size=15,
fill_color="color",
fill_alpha=0.6,
line_color=None,
legend_group="ID",
source=source,
)
p.xaxis[0].axis_label = "Principal Component 1"
p.yaxis[0].axis_label = "Principal Component 2"
labels = LabelSet(
x="pc1",
y="pc2",
text="names",
x_offset=5,
y_offset=5,
source=source,
render_mode="canvas",
)
p.add_layout(p.legend[0], "right")
p.add_layout(labels)
show(p)