散景服务器图未根据需要进行更新,并且它会不断移动并且轴信息消失 [英] Bokeh Server plot not updating as wanted, also it keeps shifting and axis information vanishes

查看:64
本文介绍了散景服务器图未根据需要进行更新,并且它会不断移动并且轴信息消失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

单击刷新按钮"后,我想用新数据更新图.但是旧的数据仍然保留在图中,并且它一直向右下移,刻度消失了.

一开始,该图看起来像我期望的那样(除了X轴信息..作为一个附带的问题,II在Bokeh属性中查找了DataSpec(),但不确定如何传递 accept_datetime = False到线图中的 x 参数.我的代码看起来像这样.)

数据目录看起来像

  root- || -weeklydata1.pkl| -weeklydata2.pkl| -datashow.py 

单击刷新后,连续执行多次刷新,图一直在移动,并且轴信息消失了.

我正在使用最新版本的Bokeh 1.4.0

解决方案

默认情况下,Bokeh在所有可用字形上自动调整范围.上面的代码将无限地累积新的字形.因此,您看到的结果是预期的.您可以尝试在更新功能中主动删除以前的圆形和线形字形,但是我不建议这样做. update 绘图的最佳方法是优化Bokeh以使其高效有效地工作,该方法是先设置所有字形一次,然后再仅更新数据.

也就是说,您需要直接使用 ColumnDataSource .我注意到你说:

我避免使用bokeh.models.ColumnDataSource,因为找不到关于如何传递数据帧的良好示例.

我不确定你在看什么.在文档和repo的 examples 文件夹中都有很多同时使用CDS和Pandas的示例.您可以通过直接修改DataFrame来初始化CDS:

  source = ColumnDataSource(df) 

然后,当您要更新时,可以执行此操作;

  source = ColumnDataSource.from_df(new_df) 

这是一个完整的原型示例:

 将pandas导入为pd从bokeh.layouts导入列从bokeh.models导入按钮,ColumnDataSource来自bokeh.plotting导入图从bokeh.io导入curdocdf = pd.DataFrame(dict(x = [1,2,3],y1 = [4,5,6],y2 = [2,3,4]))源= ColumnDataSource(df)情节= Figure()plot.line('x','y1',line_width = 3,source = source)plot.line('x','y2',line_width = 3,color ="red",source = source)def update():new_df = pd.DataFrame(dict(x = [1,2,3],y1 = [6,5,4],y2 = [4,3,2]))source.data = ColumnDataSource.from_df(new_df)按钮= Button()button.on_click(更新)curdoc().add_root(column(button,plot)) 

小抓地力:但x轴以毫秒为单位

您当然可以拥有日期时间轴,如果您要遵循的话:

https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html#datetime-axes

I want the plot to update, once I click the "refresh button", with the new data. But the old data stays in the plot, also it keeps shifting down right and the ticks vanish.

At the beginning, the plot looks what I expected (except the X axis information. As a side problem, I I looked up DataSpec() in Bokeh properties but not sure how to pass the accept_datetime=False to the x argument in the line plot. My code kind of looks like this.)

The data directory looks like

root-|
     |-weeklydata1.pkl
     |-weeklydata2.pkl
     |-datashow.py

Here is the pickled datafiles.

from bokeh.layouts import column, row
from bokeh.models.widgets import Button
from bokeh.plotting import figure, show
from pandas import *

# Callbacks
def update_data():
    # Set up plot
    global p
    global f
    # p = figure(title="testing plot")

    # Set up data
    # weeklybdxdata(1)
    print("reading new data")
    df1 = read_pickle('weeklydata2.pkl')
    for j in df1.columns:
        p.line(df1.index,
               df1[j],
               legend=j,
               line_color=f[j])
        p.circle(df1.index,
                 df1[j],
                 size=10,
                 color=f[j])
    return p

# Set up data
df =read_pickle('weeklydata1.pkl')
f = dict(OAT='green', SAT='orange', OAH='red')

# Set up plot
p = figure(title="testing plot")

for i in df.columns:
    p.line(df.index,
           df[i],
           legend=i,
           line_color=f[i])
    p.circle(df.index,
             df[i],
             size=10,
             color=f[i])

# Set up widgets
button = Button(label='Refresh')
button.on_click(update_data)
inputs = column(button)

curdoc().add_root(row(inputs, p, width=800))
curdoc().title = "Test Plot"

I avoided using bokeh.models.ColumnDataSource as I couldn't find some good examples on how to pass dataframes.

After I launch the code with bokeh serve datashow.py, the initial plot looks like this(small gripe: but with the xaxis in milliseconds)

After I click refresh, and successively do refresh multiple times, the plot keeps shifting and axis infor vanishes.

I am on the latest version of Bokeh 1.4.0

解决方案

By default, Bokeh auto-ranges over all available glyphs. And your code above infinitely accumulates new glyphs. So, the result you see is expected. You could try actively removing the previous circle and line glyphs in your update function, but that's not what I would recommend. The best way to update plots, the way that Bokeh is optimized to do efficiently and well, is to set up all your glyphs once, and then later, update only the data for them.

That is, you need to use ColumnDataSource directly. I notice you say:

I avoided using bokeh.models.ColumnDataSource as I couldn't find some good examples on how to pass dataframes.

I'm not sure where you were looking. There are lots of examples both in the docs and in the examples folder of the repo that use CDS and Pandas together. You can initialize a CDS by adapting a DataFrame directly:

source = ColumnDataSource(df)

Then later when you want to update the source, you can do;

source = ColumnDataSource.from_df(new_df)

Here is a complete prototypical example:

import pandas as pd
from bokeh.layouts import column
from bokeh.models import Button, ColumnDataSource
from bokeh.plotting import figure
from bokeh.io import curdoc

df = pd.DataFrame(dict(x=[1,2,3], y1=[4,5,6], y2=[2,3,4]))

source = ColumnDataSource(df)

plot = figure()
plot.line('x', 'y1', line_width=3, source=source)
plot.line('x', 'y2', line_width=3, color="red", source=source)

def update():
    new_df = pd.DataFrame(dict(x=[1,2,3], y1=[6,5,4], y2=[4,3,2]))
    source.data = ColumnDataSource.from_df(new_df)

button = Button()
button.on_click(update)

curdoc().add_root(column(button, plot))

small gripe: but with the xaxis in milliseconds

You can certainly have a datetime axis, if that is what you are after:

https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html#datetime-axes

这篇关于散景服务器图未根据需要进行更新,并且它会不断移动并且轴信息消失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆