javascript - bokeh scatter 3d
Cargue un archivo CSV y léelo en la aplicación web Bokeh (2)
Tengo una aplicación de trazado de Bokeh, y debo permitir que el usuario cargue un archivo CSV y modifique los gráficos de acuerdo con los datos que contiene. ¿Es posible hacer esto con los widgets disponibles de Bokeh? Muchas gracias.
Por lo que sé, no hay ningún widget nativo de Bokeh que permita subir un archivo.
Sería útil si pudieras aclarar tu configuración actual un poco más. ¿Sus tramas se ejecutan en un servidor de bokeh o simplemente a través de un script de Python que genera las tramas?
Sin embargo, en general, si necesita que esto se exponga a través de un navegador, probablemente desee que algo como Flask ejecute una página que permita al usuario subir un archivo a un directorio que el script del bokeh pueda leer y trazar.
Aunque no hay un widget Bokeh nativo para la entrada de archivos. Es bastante factible ampliar las herramientas actuales proporcionadas por Bokeh. Esta respuesta intentará guiarlo a través de los pasos para crear un widget personalizado y modificar el javascript de bokeh para leer, analizar y generar el archivo.
Primero, aunque gran parte del crédito va a la respuesta anterior de bigreddot para crear el widget. Simplemente extendí el coffescript en su respuesta para agregar una función de manejo de archivos.
Ahora comenzamos creando una nueva clase bokeh en python que enlazará con la clase javascript y mantendrá la información generada por la entrada del archivo.
models.py
from bokeh.core.properties import List, String, Dict, Int
from bokeh.models import LayoutDOM
class FileInput(LayoutDOM):
__implementation__ = ''static/js/extensions_file_input.coffee''
__javascript__ = ''./input_widget/static/js/papaparse.js''
value = String(help="""
Selected input file.
""")
file_name = String(help="""
Name of the input file.
""")
accept = String(help="""
Character string of accepted file types for the input. This should be
written like normal html.
""")
data = List(Dict(keys_type=String, values_type=Int), default=[], help="""
List of dictionary containing the inputed data. This the output of the parser.
""")
Luego creamos la implementación coffeescript para nuestra nueva clase python. En esta nueva clase, hay una función adicional de controlador de archivos que se activa al cambiar el widget de entrada de archivos. Este manejador de archivos usa PapaParse para analizar el csv y luego guarda el resultado en la propiedad de datos de la clase. El javascript para PapaParse se puede descargar en su sitio web.
Puede ampliar y modificar el analizador para la aplicación y el formato de datos que desee.
extensions_file_input.coffee
import * as p from "core/properties"
import {WidgetBox, WidgetBoxView} from "models/layouts/widget_box"
export class FileInputView extends WidgetBoxView
initialize: (options) ->
super(options)
input = document.createElement("input")
input.type = "file"
input.accept = @model.accept
input.id = @model.id
input.style = "width:" + @model.width + "px"
input.onchange = () =>
@model.value = input.value
@model.file_name = input.files[0].name
@file_handler(input)
@el.appendChild(input)
file_handler: (input) ->
file = input.files[0]
opts =
header: true,
dynamicTyping: true,
delimiter: ",",
newline: "/r/n",
complete: (results) =>
input.data = results.data
@.model.data = results.data
Papa.parse(file, opts)
export class FileInput extends WidgetBox
default_view: FileInputView
type: "FileInput"
@define {
value: [ p.String ]
file_name: [ p.String ]
accept: [ p.String ]
data : [ p.Array ]
}
A Atrás en el lado de python, podemos adjuntar un bokeh on_change a nuestra nueva clase de entrada para que se active cuando cambie la propiedad de los datos. Esto sucederá después de que se realice el análisis csv. Este ejemplo muestra la interacción deseada.
main.py
from bokeh.core.properties import List, String, Dict, Int
from bokeh.models import LayoutDOM
from bokeh.layouts import column
from bokeh.models import Button, ColumnDataSource
from bokeh.io import curdoc
from bokeh.plotting import Figure
import pandas as pd
from models import FileInput
# Starting data
x = [1, 2, 3, 4]
y = x
source = ColumnDataSource(data=dict(x=x, y=y))
plot = Figure(plot_width=400, plot_height=400)
plot.circle(''x'', ''y'', source=source, color="navy", alpha=0.5, size=20)
button_input = FileInput(id="fileSelect",
accept=".csv")
def change_plot_data(attr, old, new):
new_df = pd.DataFrame(new)
source.data = source.from_df(new_df[[''x'', ''y'']])
button_input.on_change(''data'', change_plot_data)
layout = column(plot, button_input)
curdoc().add_root(layout)
Un ejemplo de un archivo .csv para esta aplicación sería. Asegúrese de que no haya una línea adicional al final de la csv.
x,y
0,2
2,3
6,4
7,5
10,25
Para ejecutar este ejemplo correctamente, bokeh debe configurarse en su formato de archivo de aplicación apropiado.
input_widget
|
+---main.py
+---models.py
+---static
+---js
+--- extensions_file_input.coffee
+--- papaparse.js
Para ejecutar este ejemplo, debe estar en el directorio arriba del archivo más superior y ejecutar bokeh serve input_widget
en el terminal.