I was writing a function to simplify my plotting, it dose not give any error yet when I call
show(plt)
on the return value nothing happens. I'm working in a Jupyter notebook. I've alredy made a call to :
output_notebook()
Here is the function code :
def plot_dist(x, h, title, xl="X axis", yl="Y axis", categories=None, width=0.5, bottom=0, color="#DC143C", xmlo=None, ymlo=None, xlo=-18, ylo=5):
total = np.sum(h)
source = ColumnDataSource(data={
"x":x,
"h":h,
"percentages":[str(round((x*100)/total, 2)) + "%" for x in h]
})
plt = figure(
title=title,
x_axis_label=xl,
y_axis_label=yl
)
plt.vbar(
x="x",
width=width,
bottom=bottom,
top="h",
source=source,
color=color
)
if xmlo is None:
if categories is None:
raise ValueError("If no categories are provided xaxis.major_label_overrides must be defined")
plt.xaxis.major_label_overrides = {
int(x):("(" + str(c.left) + "-" + str(c.right) + "]") for x,c in enumerate(categories)
}
else:
plt.xaxis.major_label_overrides = xmlo
if ymlo is None:
plt.yaxis.major_label_overrides = { int(x):(str(int(x)/1000)+"k") for x in range(0, h.max(), math.ceil((h.max()/len(h))) )}
else:
plt.yaxis.major_label_overrides = ymlo
labels = LabelSet(
x=str(x), y=str(h), text="percentages", level="glyph",
x_offset=xlo, y_offset=ylo, source=source, render_mode="canvas"
)
plt.add_layout(labels)
return plt
And this is how it is invoked :
X = [x for x in range(0, len(grps.index))]
H = grps.to_numpy()
plt = plot_dist(X, H, "Test", "xtest", "ytest", grps.index.categories)
X
is just a list and grps
is the result of a call to pandas' DataFrame.groupby
As I said it dose not give any error so I think the problem is with the ColumnDataSource
object, I must be creating it wrong. Any help is appreciated, thanks!
Edit 1 : Apparently removing the following line solved the problem :
plt.add_layout(labels)
The plot now renders correclyt, yet I need to add the labels, any idea?
Edit 2 : Ok I've solved the problem, inspecting the web console when running the code the following error shows :
Error: attempted to retrieve property array for nonexistent field
The problem was in the following lines :
labels = LabelSet(
x=str(x), y=str(h), text="percentages", level="glyph",
x_offset=xlo, y_offset=ylo, source=source, render_mode="canvas"
)
In particular assignin x=str(x)
and y=str(h)
. Changed it to simply x="x"
and y="h"
solved it.
The problem with the code is with the labels declaration :
labels = LabelSet(
x=str(x), y=str(h), text="percentages", level="glyph",
x_offset=xlo, y_offset=ylo, source=source, render_mode="canvas"
)
It was discovered by inspecting the browser's web console, which gave the following error :
Error: attempted to retrieve property array for nonexistent field
The parameters x
and y
must refer to the names in the ColumnDataSource
object passed to the Glyph
method used to draw on the plot.
I was mistakenly passing str(x)
and str(y)
which, are the string representation of the content. I was mistakenly assuming it would refer to the string representation of the variable.
To solve the problem is sufficient to pass as values to the x
and y
parameters of the LabelSet
constructor the dictionary's keys used in the ColumnDataSource
constructor :
labels = LabelSet(
x="x", y="h", text="percentages", level="glyph",
x_offset=xlo, y_offset=ylo, source=source, render_mode="canvas"
)
In addition if the ColumnDataSource
was constructed from a DataFrame
the strings will be either the columns names, the string "index"
, if any of the data used in the plot refer to the index and this has no explicit name, or the name of the index object.
Thanks a lot to bigreddot for helping me with the problem and answer.