javascript - 使用 JavaScript Papa Parse 将 CSV 文件加载到静态 Python Bokeh Web 应用程序中

标签 javascript python bokeh papaparse

我有一个供本地使用的静态 Bokeh Web 应用程序,我希望能够使用 javascript 加载文件而不运行 python。这个想法是能够与其他非Python用户共享Bokeh output_html文件来运行它并使用文件选择器加载他们的数据以进行交互式可视化。我根据this post做了一个非常粗略的代码和 this post

我对 JS 毫无了解,对于糟糕的实现,我提前表示歉意。如果您有类似的示例或更简单的方法来读取没有 Bokeh 服务器的文件,请随意。

from bokeh.models.widgets import Toggle
from bokeh.plotting import figure, output_file, show

output_file("load_data_buttons.html")

x = [0]
y = x

source = ColumnDataSource(data=dict(x=x, y=y))

plot = figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

callback = CustomJS(args=dict(source=source), code="""
       // initialize our parsed_csv to be used wherever we want
var parsed_csv;
var start_time, end_time;

        // document.ready
        $(function() {

          $('.load-file').on('click', function(e) {
            start_time = performance.now();
            $('#report').text('Processing...');

            console.log('initialize worker');

            var worker = new Worker('worker.js');
            worker.addEventListener('message', function(ev) {
              console.log('received raw CSV, now parsing...');

              // Parse our CSV raw text
              Papa.parse(ev.data, {
                header: true,
                dynamicTyping: true,
                complete: function (results) {
                    // Save result in a globally accessible var
                  parsed_csv = results;
                  console.log('parsed CSV!');
                  console.log(parsed_csv);

                  $('#report').text(parsed_csv.data.length + ' rows processed');
                  end_time = performance.now();
                  console.log('Took ' + (end_time - start_time) + " milliseconds to load and process the CSV file.")
                }
              });

              // Terminate our worker
              worker.terminate();
            }, false);

            // Submit our file to load
            var file_to_load = document.getElementById("myFile").files[0];

            console.log('call our worker');
            worker.postMessage({file: file_to_load});
          });

        });

        x =  parsed_csv.data['x']
        y =  parsed_csv.data['y']
        #load data stored in the file name and assign to x and y
        source.trigger('change');
    """)

toggle1 = Toggle(label="Load data file 1", callback=callback)

layout = Row(toggle1, plot)

show(layout)

worker.js

self.addEventListener('message', function(e) {
    console.log('worker is running');

    var file = e.data.file;
    var reader = new FileReader();

    reader.onload = function (fileLoadedEvent) {
        console.log('file loaded, posting back from worker');

        var textFromFileLoaded = fileLoadedEvent.target.result;

        // Post our text file back from the worker
        self.postMessage(textFromFileLoaded);
    };

    // Actually load the text file
    reader.readAsText(file, "UTF-8");
}, false);

csv 文件有 x,y 数据

x   y
0   0
1   1
2   2
3   3
4   4

最佳答案

您不需要 Web Workers 来实现它,特别是如果您不熟悉 JavaScript。 我会这样做:

from bokeh.layouts import row, column
from bokeh.models import Div, ColumnDataSource, CustomJS, FileInput
from bokeh.plotting import figure, save

source = ColumnDataSource(data=dict(x=[0], y=[0]))

plot = figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

fi_label = Div(text='Load data file 1')
fi = FileInput()
status = Div()

callback = CustomJS(args=dict(source=source,
                              status=status),
                    code="""
status.text = 'Loading...';
Papa.parse(atob(cb_obj.value), {
    // For some reason, Papa didn't detect it automatically.
    delimiter: '\t',
    header: true,
    dynamicTyping: true,
    complete: function (results) {
        const acc = results.meta.fields.reduce((acc, f) => {
            acc[f] = [];
            return acc;
        }, {});
        source.data = results.data.reduce((acc, row) => {
            for (const k in acc) {
                acc[k].push(row[k]);
            }
            return acc;
        }, acc);
        status.text = 'Ready!';
    }
});
""")

fi.js_on_change('value', callback)

template = """\
{% block preamble %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"
        integrity="sha256-Fh801SO9gqegfUdkDxyzXzIUPWzO/Vatqj8uN+5xcL4="
        crossorigin="anonymous"></script>
{% endblock %}
"""
# Cannot use `show` because it doesn't have the `template` argument.
save(column(row(fi_label, fi), plot), template=template)

关于javascript - 使用 JavaScript Papa Parse 将 CSV 文件加载到静态 Python Bokeh Web 应用程序中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61356082/

相关文章:

python - uWSGI cron-like 接口(interface),基于信号的定时器

docker - 使用docker在Shinyproxy上运行bokeh

javascript - 如何使用 customjs 在 Bokeh 中动态更新下拉菜单选项

python - 这个 Bokeh 列数据源是如何工作的?

javascript - 将 QWERTY 条码扫描仪输入转换为 AZERTY

python - 不明白这个 AttributeError :'str' 对象没有属性 'text'

javascript - 使用 Firebase 规则构建数据

python - 继续执行 Python 更新脚本而不等待用户输入

javascript - CSS 将 SVG 排列成偏移网格

javascript - 无法在 selenium webdriver 中写入 Excel 工作表