切换散景服务 hbar 图的数据源不起作用:空白图
Switching data source for bokeh serve hbar plot not working: Blank plot
问题
我想创建一个交互式 hbar 图,您可以在其中使用 select 小部件、python 回调和本地散景服务在 3 个不同的数据源之间切换。使用默认源的绘图呈现良好,但当我切换到不同的源时,y 标签保持不变并且绘图变为空白。在 select 小部件上改回原始值不会显示我开始时使用的图并保持空白。
当我将初始源硬编码为代码中的另一个源时,它呈现得很好,直到我再次使用小部件切换它,所以数据本身似乎可以单独工作。
我错过了什么吗?我通读了许多主题、文档和教程,但没有发现我的代码有任何问题。
这是我到目前为止所做的:
我读取了一个 .csv 并创建了 3 个单独的数据帧,然后将其转换为列数据源。每个源都有 10 个数据条目,列为“物种”、“ci_lower”和“ci_upper”。
这是一个来源的示例(所有三个来源的构建方式完全相同,具有不同的分类单元 类):
df = pd.read_csv(os.path.join(os.path.dirname(__file__), "AZA_MLE_Jul2018_utf8.csv",), encoding='utf-8')
m_df = df[df["taxon_class"]=="Mammalia"]
m_df = m_df.sort_values(by="mle", ascending=False)
m_df = m_df.reset_index(drop=True)
m_df = m_df.head(10)
m_df = m_df.sort_values(by="species", ascending=False)
m_df = m_df.reset_index(drop=True)
m_source = bp.ColumnDataSource(m_df)
我在字典中保存了所有 3 个来源:
sources_dict={
"Mammalia": m_source,
"Aves": a_source,
"Reptilia": r_source
}
...然后创建了名为“source”的变量,默认情况下应与“Mammalia”源交互更改:
source = sources_dict["Mammalia"]
接下来我创建了一个图形并添加了一个带有源变量的 hbar 图,如下所示:
plot = bp.figure(x_range=(0, np.amax(source.data["ci_upper"])+5), y_range=source.data["species"])
plot.hbar(y="species", right="ci_lower", left="ci_upper", height=0.5, fill_color="#b3de69", source=source)
然后我添加了带有 python 回调的 select 小部件:
def select_handler(attr, old, new):
source.data["species"]=sources_dict[new].data["species"]
source.data["ci_lower"]=sources_dict[new].data["ci_lower"]
source.data["ci_upper"]=sources_dict[new].data["ci_upper"]
select = Select(title="Taxonomic Class:", value="Mammalia", options=list(sources_dict.keys()))
select.on_change("value", select_handler)
curdoc().add_root(bk.layouts.row(plot, select))
我试过这个:
我怀疑错误出在回调函数中,所以我尝试了很多不同的变体,结果都是一样的。我将在这里列出其中的一些:
我尝试使用 python 本机词典:
new_data= {
'species': sources_dict[new].data["species"],
'ci_lower': sources_dict[new].data["ci_lower"],
'ci_upper': sources_dict[new].data["ci_upper"]
}
source.data=new_data
我尝试分配整个数据源,而不仅仅是交换数据
source=sources_dict[new]
我也试过使用 dict()
source.data = dict(species=sources_dict[new].data["species"], ci_lower=sources_dict[new].data["ci_lower"], ci_upper=sources_dict[new].data["ci_upper"])
截图
这是初始情节的屏幕截图,当我 运行 带有 bokeh serve --show file.py
的 py 文件时
这是更改 selected 值后的一个:
非常感谢任何可以帮助我解决这个问题的提示
在评论中回答您的问题,更改 data
不会更改范围,因为 y_range=some_thing
只是创建一个在幕后完成的适当范围 class 的便利。
这是您可以手动完成的方法。请注意,我根本没有触及 x_range
- 默认情况下是 DataRange1d
自动计算其 start/end 值。
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models import Select, ColumnDataSource
from bokeh.plotting import figure
d1 = dict(x=[0, 1], y=['a', 'b'])
d2 = dict(x=[8, 9], y=['x', 'y'])
ds = ColumnDataSource(d1)
def get_factors(data):
return sorted(set(data['y']))
p = figure(y_range=get_factors(d1))
p.circle(x='x', y='y', source=ds)
s = Select(options=['1', '2'], value='1')
def update(attr, old, new):
if new == '1':
ds.data = d1
else:
ds.data = d2
p.y_range.factors = get_factors(ds.data)
s.on_change('value', update)
curdoc().add_root(column(p, s))
问题
我想创建一个交互式 hbar 图,您可以在其中使用 select 小部件、python 回调和本地散景服务在 3 个不同的数据源之间切换。使用默认源的绘图呈现良好,但当我切换到不同的源时,y 标签保持不变并且绘图变为空白。在 select 小部件上改回原始值不会显示我开始时使用的图并保持空白。 当我将初始源硬编码为代码中的另一个源时,它呈现得很好,直到我再次使用小部件切换它,所以数据本身似乎可以单独工作。
我错过了什么吗?我通读了许多主题、文档和教程,但没有发现我的代码有任何问题。
这是我到目前为止所做的:
我读取了一个 .csv 并创建了 3 个单独的数据帧,然后将其转换为列数据源。每个源都有 10 个数据条目,列为“物种”、“ci_lower”和“ci_upper”。 这是一个来源的示例(所有三个来源的构建方式完全相同,具有不同的分类单元 类):
df = pd.read_csv(os.path.join(os.path.dirname(__file__), "AZA_MLE_Jul2018_utf8.csv",), encoding='utf-8')
m_df = df[df["taxon_class"]=="Mammalia"]
m_df = m_df.sort_values(by="mle", ascending=False)
m_df = m_df.reset_index(drop=True)
m_df = m_df.head(10)
m_df = m_df.sort_values(by="species", ascending=False)
m_df = m_df.reset_index(drop=True)
m_source = bp.ColumnDataSource(m_df)
我在字典中保存了所有 3 个来源:
sources_dict={
"Mammalia": m_source,
"Aves": a_source,
"Reptilia": r_source
}
...然后创建了名为“source”的变量,默认情况下应与“Mammalia”源交互更改:
source = sources_dict["Mammalia"]
接下来我创建了一个图形并添加了一个带有源变量的 hbar 图,如下所示:
plot = bp.figure(x_range=(0, np.amax(source.data["ci_upper"])+5), y_range=source.data["species"])
plot.hbar(y="species", right="ci_lower", left="ci_upper", height=0.5, fill_color="#b3de69", source=source)
然后我添加了带有 python 回调的 select 小部件:
def select_handler(attr, old, new):
source.data["species"]=sources_dict[new].data["species"]
source.data["ci_lower"]=sources_dict[new].data["ci_lower"]
source.data["ci_upper"]=sources_dict[new].data["ci_upper"]
select = Select(title="Taxonomic Class:", value="Mammalia", options=list(sources_dict.keys()))
select.on_change("value", select_handler)
curdoc().add_root(bk.layouts.row(plot, select))
我试过这个:
我怀疑错误出在回调函数中,所以我尝试了很多不同的变体,结果都是一样的。我将在这里列出其中的一些:
我尝试使用 python 本机词典:
new_data= {
'species': sources_dict[new].data["species"],
'ci_lower': sources_dict[new].data["ci_lower"],
'ci_upper': sources_dict[new].data["ci_upper"]
}
source.data=new_data
我尝试分配整个数据源,而不仅仅是交换数据
source=sources_dict[new]
我也试过使用 dict()
source.data = dict(species=sources_dict[new].data["species"], ci_lower=sources_dict[new].data["ci_lower"], ci_upper=sources_dict[new].data["ci_upper"])
截图
这是初始情节的屏幕截图,当我 运行 带有 bokeh serve --show file.py
的 py 文件时这是更改 selected 值后的一个:
非常感谢任何可以帮助我解决这个问题的提示
在评论中回答您的问题,更改 data
不会更改范围,因为 y_range=some_thing
只是创建一个在幕后完成的适当范围 class 的便利。
这是您可以手动完成的方法。请注意,我根本没有触及 x_range
- 默认情况下是 DataRange1d
自动计算其 start/end 值。
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models import Select, ColumnDataSource
from bokeh.plotting import figure
d1 = dict(x=[0, 1], y=['a', 'b'])
d2 = dict(x=[8, 9], y=['x', 'y'])
ds = ColumnDataSource(d1)
def get_factors(data):
return sorted(set(data['y']))
p = figure(y_range=get_factors(d1))
p.circle(x='x', y='y', source=ds)
s = Select(options=['1', '2'], value='1')
def update(attr, old, new):
if new == '1':
ds.data = d1
else:
ds.data = d2
p.y_range.factors = get_factors(ds.data)
s.on_change('value', update)
curdoc().add_root(column(p, s))