Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Bokeh-如何从EventHandler函数返回对象_Python_Flask_Widget_Bokeh - Fatal编程技术网

Python Bokeh-如何从EventHandler函数返回对象

Python Bokeh-如何从EventHandler函数返回对象,python,flask,widget,bokeh,Python,Flask,Widget,Bokeh,我想在bokeh应用程序中单击上载按钮(代码来自)时返回data.frame对象。下面的代码 ## Load library import pandas as pd from xlrd import XLRDError import io import base64 from bokeh.layouts import row, column, widgetbox, layout from bokeh.models import ColumnDataSource, CustomJS from b

我想在bokeh应用程序中单击上载按钮(代码来自)时返回data.frame对象。下面的代码

## Load library
import pandas as pd
from xlrd import XLRDError
import io
import base64

from bokeh.layouts import row, column, widgetbox, layout
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.models.widgets import Button, Div, TextInput, DataTable, TableColumn, Panel, Tabs
from bokeh.io import curdoc
from bokeh.plotting import figure

sheet_names_expected = ['Sheet'+str(i) for i in range(1,7)]
## Uploaded Data Handling 
file_source = ColumnDataSource({'file_contents':[], 'file_name':[], 'upload_message':[]})

def file_callback(attr,old,new):
    print('filename:', file_source.data['file_name'])
    #print('filename:', type(file_source.data['file_contents'][0]))
    raw_contents = file_source.data['file_contents'][0]

    prefix, b64_contents = raw_contents.split(",", 1)
    file_contents = base64.b64decode(b64_contents)
    file_io = io.BytesIO(file_contents)

    try:
        df_dict = pd.read_excel(file_io, sheet_name = sheet_names_expected)
        file_source.data['upload_message'] = 'Successfully loaded data'
    except XLRDError:
        file_source.data['upload_message'] = 'One or more of the sheet names are mis-spelled/missing.\n'
    except :
        file_source.data['upload_message'] = 'Error occured while uploading the file. Ensure it\'s a xlsx file'

## How to now have the 6 dataframes within `df_dict` outside the callback function for further analysis and plotting ?



file_source.on_change('data', file_callback)
###########################################################################
## Upload Button Widget
###########################################################################
button = Button(label="Upload Data", button_type="success")
# when butotn is clicked, below code in CustomJS will be called
button.callback = CustomJS(args=dict(file_source=file_source), code = """
function read_file(filename) {
    var reader = new FileReader();
    reader.onload = load_handler;
    reader.onerror = error_handler;
    // readAsDataURL represents the file's data as a base64 encoded string
    reader.readAsDataURL(filename);
}

function load_handler(event) {
    var b64string = event.target.result;
    file_source.data = {'file_contents' : [b64string], 'file_name':[input.files[0].name]};
    file_source.trigger("change");
}

function error_handler(evt) {
    if(evt.target.error.name == "NotReadableError") {
        alert("Can't read file!");
    }
}

var input = document.createElement('input');
input.setAttribute('type', 'file'); 
input.onchange = function(){
    if (window.FileReader) {
        read_file(input.files[0]);
    } else {
        alert('FileReader is not supported in this browser');
    }
}
input.click();
""")

不确定如何使用ColumnDataSource。excel文件有6个选项卡,因此6个数据框将由
pd读取到字典中。read\u excel()

如果我正确理解您的问题,那么我认为您对bokeh的工作原理有些困惑。我建议您通读文档,了解图库中的一些示例是如何工作的

尽管如此,我相信您需要使用ColumnDataSource来实现您想要的。首先可以读入数据,然后将其加载到一个或多个ColumnDataSource中。然后,当您按下按钮时,它将执行回调函数中的所有代码。请看这里:

这里的回调函数执行以下操作:
1:访问现有列源数据
2:运行其他python函数,然后
3:更新存储在CD中的现有数据。这将自动更新绘图

如果不使用列数据源,则在不重新创建绘图并更新其中显示的html文档的情况下,无法更新绘图

from os.path import dirname, abspath
import pandas as pd
from bokeh.layouts import row
from bokeh.plotting import figure
from bokeh.plotting import curdoc
from bokeh.models.widgets import Button
from bokeh.models import ColumnDataSource

button = Button(label='Click')

# replace this with file i/o
df = pd.DataFrame({'x':[1,2,3,4],'y':[10,20,30,40]})

# create a column data source from the read in data
# source.data = dictionary containing the data
# using a CDS will allow any plots or tables
# to automatically update when the source.data
# is modified

source = ColumnDataSource(df)

def mycalc(x):
    """
    Arbitary python function
    """
    x *= 2
    return x


def callback():
    x = source.data['x']
    # compute python based functions here to manipulate data
    x = mycalc(x)
    # update the column data source with the new data
    source.data['x'] = x

p = figure(plot_width=400, plot_height=400)

p.circle('x','y', source=source)

button.on_click(callback)
curdoc().add_root(row([button, p]))

您想对这些数据做什么?您是在尝试更新某些图表或表格,还是使用另一个python函数执行计算?@Anthonydouc首先使用另一个python函数执行计算,然后再绘制一些图表。嘿,谢谢分享。但是,我有一个上传
按钮
,它将为我提供数据。因此,数据源对我来说不是固定的。这就是我需要在
回调函数中读取的原因。我也将用这个来编辑我的问题,我的错误是“你正在绘制的列是否已修复?”?如果是,CDS数据字段可以固定,但上传时数据会更改。您可以使用上载的数据更新CD中包含的数据,这些数据将传播到绘图。否,数据格式将不同。例如,表中的每台机器都是一列。因此,如果安装了计算机,则上载的数据将有更多列。因此,我需要它是动态的。有什么建议吗?你能更好地解释数据的哪些部分正在被绘制或制表吗。绘图的数量或正在绘图的数据字段的数量也是可变的吗?你能做的只有这么多-更新现有绘图/表格、添加新数据系列或使用新数据创建新绘图。不,你可以添加新字段并向现有图形添加新图示符。例如,每次按下按钮时,你可以添加与新字段对应的新圆。我只是不知道你的问题到底是什么。