问题
I want to plot a vertical line in holoviews
with the bokeh
backend which has a label that shows up in my legend. I need this line to be the full height of the plot, regardless of whether it is alone or overlaid with other elements. How can I achieve this?
Example
I'm adding in a curve plot in the example because otherwise even elements that can appear in a legend just use their label as a title.
import numpy as np
import holoviews as hv
hv.extension("bokeh")
x = np.linspace(0, 1)
curve = hv.Curve((x, np.sin(x)), label="sin(x)")
vline = hv.VLine(0.5, label="vline")
curve * vline
This gives the following plot:
which has no label for the vertical line. How do I get the label to show up?
回答1:
As mentioned in this issue but not yet in the docs, VLine
and HLine
don't appear in legends, and there is no plan to add support for them (basically, in bokeh
they're created differently, so there's not an easy way to put them in the legend). One can use Spikes
instead. However, as documented in another issue, spikes don't overlay well. In particular, they don't adjust their height to be the full height of the plot if given no explicit height. Here are two workarounds that I've come up with.
Workaround 1
You can explicitly find out the height of the other element that the vertical line should be overlaid with and use this to create a spike of the proper height. This works, but it's rather brittle because you need to adapt it with full knowledge of everything that could be overlaid with the spike.
import numpy as np
import holoviews as hv
hv.extension("bokeh")
x = np.linspace(0, 1)
curve = hv.Curve((x, np.sin(x)), label="sin(x)")
height = curve.data["y"].max() - curve.data["y"].min()
spikes = hv.Spikes(([0.5], [height]), vdims="height", label="mid")
spikes * curve
Workaround 2
This uses both a VLine
and a Spikes
. The spike won't be visible except that it will contribute an entry to the legend. The vline will be on top of the spike, and vlines already adjust themselves to fill the whole height of the figure. This requires creating an extra element, but it is more robust because you can overlay the product of this spike and vline with any other elements and still get a line that fills the height of the plot and appears in the legend. As the legend entry is based on the spike, though, it will only look like the vline if you make sure that they have a similar appearance (e.g. the vline and the spike have the same color).
# need to make sure the colors are the same for spikes/vlines
# would look a bit better if I adjusted the spike thickness too
spikes = hv.Spikes([0.5], label="mid").opts(color="black")
vline = hv.VLine(0.5).opts(color="black")
spikes * curve * vline
In the future, Spikes
will hopefully scale themselves to be full-height when not explicitly given a height, and then these workarounds won't be needed.
来源:https://stackoverflow.com/questions/55050557/how-do-i-get-a-full-height-vertical-line-with-a-legend-label-in-holoviews-boke