How to add legend for (stacked) area plots?

Is there a way to add legend for stacked areas as demonstrated?
E.g. in the example code here

values = np.random.rand(5, 20)
percentages = (values/values.sum(axis=0)).T*100

overlay = hv.Overlay([hv.Area(percentages[:, i], vdims=[hv.Dimension('value', unit='%')]) for i in range(5)])
overlay + hv.Area.stack(overlay)

The option show_legend=True does not work here.

It seems that when areas are stacked only one of the legend gets plotted:

bokeh_plot (4) bokeh_plot (5)

Is there a way to display all legend?

OK the source (and cause for this behavior) is here:

It is always the last element that is cloned, hence the last label carries over.

A fix:

def my_Area_stack(areas, baseline_name='Baseline'):
    fixes buggy behavior in hv.Area.stack
    if not len(areas):
        return areas
    assert isinstance(areas, hv.Overlay)
    areas = hv.NdOverlay({i: el for i, el in enumerate(areas)})
    df = areas.dframe(multi_index=True)
    levels = list(range(areas.ndims))
    vdim = areas.last.vdims[0]
    vdims = [vdim, baseline_name]
    baseline = None
    stacked = areas.clone(shared_data=False)
    for key, sdf in df.groupby(level=levels):
        sdf = sdf.droplevel(levels).reindex(index=df.index.levels[-1], fill_value=0)
        if baseline is None:
            sdf[baseline_name] = 0
            sdf[] = sdf[] + baseline
            sdf[baseline_name] = baseline
        baseline = sdf[]
        stacked[key] = areas[key].clone(sdf, vdims=vdims)
    return hv.Overlay(stacked.values())

This look like a bug to me, I think you should make an issue/PR on Github.


Hi @Hoxbro,

Thank you for submitting the Issue!

(I wasn’t sure what the condition isinstance(areas, hv.Overlay) was for, and if I broke anything by changing that line. I will comment in the Issue on Github.)