使用 JavaScript Papa Parse 将 CSV 文件加载到静态 Python Bokeh Web 应用程序
Load CSV file into static Python Bokeh Web app with JavaScript Papa Parse
我有一个供本地使用的静态 Bokeh Web 应用程序,我希望能够使用 javascript 加载文件而无需 运行ning python。这个想法是能够与其他非 python 用户共享 Bokeh output_html 文件 运行 它并使用文件选择器加载他们的数据以进行交互式可视化。我根据 and
做了一个非常粗略的代码
我对 JS 一无所知,对于糟糕的实现,我提前表示歉意。如果您有类似的示例或更简单的方法来读取没有散景服务器的文件,请随意。
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 Worker 来实现它,尤其是当您对 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)
我有一个供本地使用的静态 Bokeh Web 应用程序,我希望能够使用 javascript 加载文件而无需 运行ning python。这个想法是能够与其他非 python 用户共享 Bokeh output_html 文件 运行 它并使用文件选择器加载他们的数据以进行交互式可视化。我根据
我对 JS 一无所知,对于糟糕的实现,我提前表示歉意。如果您有类似的示例或更简单的方法来读取没有散景服务器的文件,请随意。
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 Worker 来实现它,尤其是当您对 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)