上传 CSV 文件并在 Bokeh Web 应用程序中读取 [英] Upload a CSV file and read it in Bokeh Web app

查看:26
本文介绍了上传 CSV 文件并在 Bokeh Web 应用程序中读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个散景绘图应用程序,我需要允许用户上传 CSV 文件并根据其中的数据修改绘图.是否可以使用 Bokeh 的可用小部件来做到这一点?非常感谢你.

I have a Bokeh plotting app, and I need to allow the user to upload a CSV file and modify the plots according to the data in it. Is it possible to do this with the available widgets of Bokeh? Thank you very much.

推荐答案

虽然没有用于文件输入的原生 Bokeh 小部件.扩展 Bokeh 提供的当前工具是完全可行的.此答案将尝试指导您完成创建自定义小部件和修改散景 javascript 以读取、解析和输出文件的步骤.

Although there is no native Bokeh widget for file input. It is quite doable to extend the current tools provided by Bokeh. This answer will try to guide you through the steps of creating a custom widget and modifying the bokeh javascript to read, parse and output the file.

首先,虽然很多功劳归于 bigreddot 的先前答案,但创建小部件.我只是在他的回答中扩展了咖啡脚本以添加文件处理功能.

First though a lot of the credit goes to bigreddot's previous answer on creating the widget. I simply extended the coffescript in his answer to add a file handling function.

现在我们开始在 python 上创建一个新的散景类,它将链接到 javascript 类并保存文件输入生成的信息.

Now we begin by creating a new bokeh class on python which will link up to the javascript class and hold the information generated by the file input.

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.
""")

然后我们为我们的新 python 类创建 coffeescript 实现.在这个新类中,添加了一个文件处理函数,该函数在文件输入小部件的更改时触发.此文件处理程序使用 PapaParse 解析 csv,然后将结果保存在类的数据属性中.PapaParse 的 javascript 可以在他们的网站上下载.

Then we create the coffeescript implementation for our new python class. In this new class, there is an added file handler function which triggers on change of the file input widget. This file handler uses PapaParse to parse the csv and then saves the result in the class's data property. The javascript for PapaParse can be downloaded on their website.

您可以针对所需的应用程序和数据格式扩展和修改解析器.

You can extend and modify the parser for your desired application and data format.

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: "
",
      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 ]
  }

一个回到 python 端,我们可以将散景 on_change 附加到我们的新输入类,以便在它的数据属性更改时触发.这将在 csv 解析完成后发生.此示例展示了所需的交互.

A Back on the python side we can then attach a bokeh on_change to our new input class to trigger when it's data property changes. This will happen after the csv parsing is done. This example showcases the desired interaction.

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)

此应用程序的 .csv 文件示例如下.确保 csv 末尾没有多余的行.

An example of a .csv file for this application would be. Make sure there is no extra line at the end of the csv.

x,y
0,2
2,3
6,4
7,5
10,25

要正确运行此示例,必须以正确的应用程序文件树格式设置散景.

To run this example properly, bokeh must be set up in it's proper application file tree format.

input_widget
   |
   +---main.py
   +---models.py
   +---static
        +---js
            +--- extensions_file_input.coffee
            +--- papaparse.js

要运行此示例,您需要在最顶层文件上方的目录中并在终端中执行 bokeh serve input_widget.

To run this example, you need to be in the directory above the top most file and execute bokeh serve input_widget in the terminal.

这篇关于上传 CSV 文件并在 Bokeh Web 应用程序中读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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