Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Legend is wrongly defined when overlaying color-encoded categorical points #6691

@maximlt

Description

@maximlt

In this issue, two Points elements are created with the color encoded with the color plot option set to the same dimension. One element contains all the categories found in that dimension, the other one only contains a subset. Overlaying these two elements results in a legend whose colormapping is broken.

import colorcet as cc
import holoviews as hv
from bokeh.sampledata.autompg import autompg

hv.extension('bokeh')

autompg.yr = autompg.yr.apply(lambda x: str(x))

p1 = hv.Points(
    autompg, ['weight', 'accel'], ['yr']
).opts(
    color=hv.dim('yr'),
    show_legend=True,
    cmap=cc.b_glasbey_category10,
    width=350, height=350,
)

p2 = hv.Points(
    autompg.iloc[-100:, :], ['weight', 'accel'], ['yr']
).opts(
    color=hv.dim('yr'),
    show_legend=True,
    cmap=cc.b_glasbey_category10,
    width=350, height=350,
)

OK
Image

OK-ish
Image

Not OK
Image

When the categories are totally disjoint, the legend also appears to be broken.

p1 = hv.Points(
    autompg[autompg.yr.isin(['70', '71', '72'])], ['weight', 'accel'], ['yr']
).opts(
    color=hv.dim('yr'),
    show_legend=True,
    cmap=cc.b_glasbey_category10,
    width=350, height=350,
)

p2 = hv.Points(
    autompg[autompg.yr.isin(['79', '80', '81'])], ['weight', 'accel'], ['yr']
).opts(
    color=hv.dim('yr'),
    show_legend=True,
    cmap=cc.b_glasbey_category10,
    width=350, height=350,
)
Image

This issue was found (in holoviz-topics/hv-anndata#59) when creating a linked selection from an element like p1. The linked selection is internally implemented as an overlay of two base elements (plus elements representing the selected region). When an area is selected on the plot, the legend is dynamically updated, in the same broken way as reported above.

import colorcet as cc
import holoviews as hv
from bokeh.sampledata.autompg import autompg

hv.extension('bokeh')

autompg.yr = autompg.yr.apply(lambda x: str(x))

ls = hv.link_selections.instance()

plot = hv.Points(
    autompg, ['weight', 'accel'], ['yr']
).opts(
    color=hv.dim('yr'),
    show_legend=True,
    cmap=cc.b_glasbey_category10,
    width=350, height=350,
)
lplot = ls(plot)
lplot
issue.ls.color.mp4

Note that I've tried the NdOverlay approach, except that it's excruciatingly slow (end up with a dynamic overlay of NdOverlays) and also appears a bit broken (see the first item in the legend and its funky selected region).

ls = hv.link_selections.instance()

plot = hv.Points(
    autompg, ['weight', 'accel'], ['yr']
).groupby(
    'yr',
    hv.NdOverlay
).opts(
    show_legend=True,
    width=350, height=350,
)
lplot = ls(plot)
lplot.opts(hv.opts.Points(color=hv.Cycle(values=cc.b_glasbey_category10)))
Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: bugSomething isn't correct or isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions