散景多个图表链接行为
bokeh multiple charts linking behaviour
我有两个图表。当我放大顶部或底部图表时,x 轴都会更新并显示相同的日期范围,这很好。问题是两个图表上的 y 轴完全不同,所以当我放大顶部图表时,x 轴和 y 轴的比例相应地缩放。在底部图表上,虽然 x 轴相应地缩放,但 y 轴没有。我不能使用 y_range=fig.y_range 因为 y 范围非常不同。
当两个图表具有不同的 y 轴范围时,当我放大顶部图表时底部图表的 y 轴是否可以相应缩放?
更新 - 我的意思是相应的
假设我的 x 轴从 2020 年 1 月 1 日到 2020 年 12 月 31 日。现在假设我使用内置工具在顶部图表上放大整个 2020 年 7 月,底部图表的 x 轴会相应调整自动地,即 x 轴现在在两个图表上都放大了整个 7 月。通过使用行 x_range=fig.x_range,这项工作非常出色。两个图表共享相同的 x 轴。
但是他们的 y 轴不同所以我不能使用 y_range=fig.y_range.
所以我想做的是,当我放大顶部图表时,x 轴和 y 轴会自动重新缩放。我希望底部图表的 y 轴也重新缩放(已经提到的 x 轴会自动执行此操作)。
下面是我的代码
cds = ColumnDataSource(data=df)
fig = figure(plot_width=W_PLOT, plot_height=H_PLOT,
tools=TOOLS,
x_axis_type="datetime",
title=name,
toolbar_location='above')
# lets add a moving average
fig.line(x='time_stamp', y='ma_20', source=cds, legend_label='MA 20')
fig_ind = figure(plot_width=W_PLOT, plot_height=H_PLOT_IND,
tools=TOOLS,
x_axis_type="datetime",
x_range=fig.x_range)
fig_ind.line(x='time_stamp', y='ma_100', source=cds, legend_label='MA 100')
show(gridplot([[fig],[fig_ind]]))
以下是如何在公共 X 范围上使用 CustomJS
回调来实现此目的:
from bokeh.models.ranges import DataRange1d
from bokeh.layouts import column
from bokeh.models.sources import ColumnDataSource
from bokeh.models import CustomJS
import pandas as pd
import numpy as np
df = pd.DataFrame(
{
'fig1_y': np.linspace(0, 100, 100),
'fig2_y': np.linspace(0, 1000, 100),
'common_x': pd.date_range(
start='2020-01-01',
end='2021-01-01',
periods=100
)
}
)
cds = ColumnDataSource(data=df)
common_x_range = DataRange1d(bounds='auto')
fig = figure(
plot_width=500,
plot_height=200,
x_axis_type="datetime",
x_range=common_x_range
)
fig.line(
x='common_x',
y='fig1_y',
source=cds,
legend_label='MA 20'
)
fig2 = figure(
plot_width=500,
plot_height=200,
x_axis_type="datetime",
x_range=common_x_range,
y_range=DataRange1d(bounds='auto')
)
fig2.line(
x='common_x',
y='fig2_y',
source=cds,
legend_label='MA 100'
)
callback = CustomJS(
args={
'y_range': fig2.y_range,
'source': cds
}, code='''
var x_data = source.data.common_x,
fig2_y = source.data.fig2_y,
start = cb_obj.start,
end = cb_obj.end,
min = Infinity,
max = -Infinity;
for (var i=0; i < x_data.length; ++i) {
if (start <= x_data[i] && x_data[i] <= end) {
max = Math.max(fig2_y[i], max);
min = Math.min(fig2_y[i], min);
}
}
y_range.start = min
y_range.end = max
''')
common_x_range.js_on_change('start', callback)
common_x_range.js_on_change('end', callback)
show(column([fig,fig2]))
我有两个图表。当我放大顶部或底部图表时,x 轴都会更新并显示相同的日期范围,这很好。问题是两个图表上的 y 轴完全不同,所以当我放大顶部图表时,x 轴和 y 轴的比例相应地缩放。在底部图表上,虽然 x 轴相应地缩放,但 y 轴没有。我不能使用 y_range=fig.y_range 因为 y 范围非常不同。
当两个图表具有不同的 y 轴范围时,当我放大顶部图表时底部图表的 y 轴是否可以相应缩放?
更新 - 我的意思是相应的
假设我的 x 轴从 2020 年 1 月 1 日到 2020 年 12 月 31 日。现在假设我使用内置工具在顶部图表上放大整个 2020 年 7 月,底部图表的 x 轴会相应调整自动地,即 x 轴现在在两个图表上都放大了整个 7 月。通过使用行 x_range=fig.x_range,这项工作非常出色。两个图表共享相同的 x 轴。
但是他们的 y 轴不同所以我不能使用 y_range=fig.y_range.
所以我想做的是,当我放大顶部图表时,x 轴和 y 轴会自动重新缩放。我希望底部图表的 y 轴也重新缩放(已经提到的 x 轴会自动执行此操作)。
下面是我的代码
cds = ColumnDataSource(data=df)
fig = figure(plot_width=W_PLOT, plot_height=H_PLOT,
tools=TOOLS,
x_axis_type="datetime",
title=name,
toolbar_location='above')
# lets add a moving average
fig.line(x='time_stamp', y='ma_20', source=cds, legend_label='MA 20')
fig_ind = figure(plot_width=W_PLOT, plot_height=H_PLOT_IND,
tools=TOOLS,
x_axis_type="datetime",
x_range=fig.x_range)
fig_ind.line(x='time_stamp', y='ma_100', source=cds, legend_label='MA 100')
show(gridplot([[fig],[fig_ind]]))
以下是如何在公共 X 范围上使用 CustomJS
回调来实现此目的:
from bokeh.models.ranges import DataRange1d
from bokeh.layouts import column
from bokeh.models.sources import ColumnDataSource
from bokeh.models import CustomJS
import pandas as pd
import numpy as np
df = pd.DataFrame(
{
'fig1_y': np.linspace(0, 100, 100),
'fig2_y': np.linspace(0, 1000, 100),
'common_x': pd.date_range(
start='2020-01-01',
end='2021-01-01',
periods=100
)
}
)
cds = ColumnDataSource(data=df)
common_x_range = DataRange1d(bounds='auto')
fig = figure(
plot_width=500,
plot_height=200,
x_axis_type="datetime",
x_range=common_x_range
)
fig.line(
x='common_x',
y='fig1_y',
source=cds,
legend_label='MA 20'
)
fig2 = figure(
plot_width=500,
plot_height=200,
x_axis_type="datetime",
x_range=common_x_range,
y_range=DataRange1d(bounds='auto')
)
fig2.line(
x='common_x',
y='fig2_y',
source=cds,
legend_label='MA 100'
)
callback = CustomJS(
args={
'y_range': fig2.y_range,
'source': cds
}, code='''
var x_data = source.data.common_x,
fig2_y = source.data.fig2_y,
start = cb_obj.start,
end = cb_obj.end,
min = Infinity,
max = -Infinity;
for (var i=0; i < x_data.length; ++i) {
if (start <= x_data[i] && x_data[i] <= end) {
max = Math.max(fig2_y[i], max);
min = Math.min(fig2_y[i], min);
}
}
y_range.start = min
y_range.end = max
''')
common_x_range.js_on_change('start', callback)
common_x_range.js_on_change('end', callback)
show(column([fig,fig2]))