Bra*_*wed 5 plot axis python-3.x bokeh holoviews
我试图绘制一组图形,上面覆盖着一个显示它们之间百分比差异的图。
我用于绘图的代码:
%%output size = 200
%%opts Curve[height=200, width=400,show_grid=True,tools=['hover','box_select'], xrotation=90]
%%opts Curve(line_width=1)
from bokeh.models import Range1d, LinearAxis
new_df = new_df.astype('float')
percent_diff_df = percent_diff_df.astype('float')
def twinx(plot, element):
# Setting the second y axis range name and range
start, end = (element.range(1))
label = element.dimensions()[1].pprint_label
plot.state.extra_y_ranges = {"foo": Range1d(start=0, end=150)}
# Adding the second axis to the plot.
linaxis = LinearAxis(axis_label='% Difference', y_range_name='foo')
plot.state.add_layout(linaxis, 'right')
wavelength = hv.Dimension('wavelength', label = 'Wavelength', unit = 'nm')
radiance = hv.Dimension('radiance', label = 'Radiance', unit = 'W/m^2/sr/nm')
curve = hv.Curve((new_df['Wave'], new_df['Level_9']), wavelength, radiance,label = 'Level_9', group = 'Requirements')*\
hv.Curve((new_df['gcal_wave'],new_df['gcal_9']),wavelength, radiance,label = 'GCAL_9', group = 'Requirements')
curve2 = hv.Curve((percent_diff_df['pdiff_wave'],percent_diff_df['pdiff_9']), label = '% Difference', group = 'Percentage Difference').opts(plot=dict(finalize_hooks=[twinx]), style=dict(color='purple'))
curve * curve2
Run Code Online (Sandbox Code Playgroud)
我需要在两个尺度上绘制这两个图。我似乎能够添加一个比例,但不能将任何图附加到比例上。
您的解决方案几乎完成。要实际使用您在钩子中创建的范围和轴,您需要访问底层散景字形并设置其 y_range_name。
一般示例如下所示:
import pandas as pd
import holoviews as hv
from bokeh.models.renderers import GlyphRenderer
hv.extension('bokeh')
def apply_formatter(plot, element):
p = plot.state
# create secondary range and axis
p.extra_y_ranges = {"twiny": Range1d(start=0, end=35)}
p.add_layout(LinearAxis(y_range_name="twiny"), 'right')
# set glyph y_range_name to the one we've just created
glyph = p.select(dict(type=GlyphRenderer))[0]
glyph.y_range_name = 'twiny'
dts = pd.date_range('2015-01-01', end='2015-01-10').values
c_def = hv.Curve((dts, np.arange(10)), name='default_axis').options(color='red', width=300)
c_sec = hv.Curve((dts, np.arange(10)), name='secondary_axis').options(color='blue',width=300, hooks=[apply_formatter])
c_def + c_def * c_sec + c_sec
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅此处的原始 github 问题:https : //github.com/pyviz/holoviews/issues/396
已编辑 - 高级示例
自从原始问题得到回答以来已经有一段时间了,随着 github 上的线程的进展,我想交叉发布一个更高级的示例,以解决原始答案中显示的一些不一致问题。我仍然鼓励您通过 github 上的线程深入了解细节,因为全息视图中的多轴图目前需要了解散景如何处理多轴。
import pandas as pd
import streamz
import streamz.dataframe
import holoviews as hv
from holoviews import opts
from holoviews.streams import Buffer
from bokeh.models import Range1d, LinearAxis
hv.extension('bokeh')
def plot_secondary(plot, element):
'''
A hook to put data on secondary axis
'''
p = plot.state
# create secondary range and axis
if 'twiny' not in [t for t in p.extra_y_ranges]:
# you need to manually recreate primary axis to avoid weird behavior if you are going to
# use secondary_axis in your plots. From what i know this also relates to the way axis
# behave in bokeh and unfortunately cannot be modified from hv unless you are
# willing to rewrite quite a bit of code
p.y_range = Range1d(start=0, end=10)
p.y_range.name = 'default'
p.extra_y_ranges = {"twiny": Range1d(start=0, end=10)}
p.add_layout(LinearAxis(y_range_name="twiny"), 'right')
# set glyph y_range_name to the one we've just created
glyph = p.renderers[-1]
glyph.y_range_name = 'twiny'
# set proper range
glyph = p.renderers[-1]
vals = glyph.data_source.data['y'] # ugly hardcoded solution, see notes below
p.extra_y_ranges["twiny"].start = vals.min()* 0.99
p.extra_y_ranges["twiny"].end = vals.max()* 1.01
# define two streamz random dfs to sim data for primary and secondary plots
simple_sdf = streamz.dataframe.Random(freq='10ms', interval='100ms')
secondary_sdf = streamz.dataframe.Random(freq='10ms', interval='100ms')
# do some transformation
pdf = (simple_sdf-0.5).cumsum()
sdf = (secondary_sdf-0.5).cumsum()
# create streams for holoviews from these dfs
prim_stream = Buffer(pdf.y)
sec_stream = Buffer(sdf.y)
# create dynamic maps to plot streaming data
primary = hv.DynamicMap(hv.Curve, streams=[prim_stream]).opts(width=400, show_grid=True, framewise=True)
secondary = hv.DynamicMap(hv.Curve, streams=[sec_stream]).opts(width=400, color='red', show_grid=True, framewise=True, hooks=[plot_secondary])
secondary_2 = hv.DynamicMap(hv.Curve, streams=[prim_stream]).opts(width=400, color='yellow', show_grid=True, framewise=True, hooks=[plot_secondary])
# plot these maps on the same figure
primary * secondary * secondary_2
Run Code Online (Sandbox Code Playgroud)