zoukankan      html  css  js  c++  java
  • 利用 Flask 动态展示 Pyecharts 图表数据的几种方法

    本文将介绍如何在 web 框架 Flask 中使用可视化工具 pyecharts, 看完本教程你将掌握几种动态展示可视化数据的方法,不会的话你来找我呀…

    Flask 模板渲染

    1. 新建一个项目flask_pyecharts

    在编辑器中选择 New Project,然后选择 Flask,创建完之后,Pycharm 会帮我们把启动脚本和模板文件夹都建好

    2. 拷贝 pyecharts 模板

    将链接中的以下模板
    ├── jupyter_lab.html
    ├── jupyter_notebook.html
    ├── macro
    ├── nteract.html
    ├── simple_chart.html
    ├── simple_page.html
    └── table.html
    全部拷贝到 tempaltes 文件夹中
    https://github.com/pyecharts/pyecharts/tree/master/pyecharts/render/templates

    3.渲染图表

    主要目标是将 pyecharts 生成的图表数据在视图函数中返回,所以我们直接在 app.py 中修改代码,如下:

    from flask import Flask
    from jinja2 import Markup
    
    
    from pyecharts import options as opts
    from pyecharts.charts import Bar
    
    app = Flask(__name__, static_folder="templates")
    
    
    def bar_base() -> Bar:
        c = (
            Bar()
                .add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
                .add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
                .add_yaxis("商家B", [15, 25, 16, 55, 48, 8])
                .set_global_opts(title_opts=opts.TitleOpts(title="Bar-基本示例", subtitle="我是副标题"))
        )
        return c
    
    
    @app.route("/")
    def index():
        c = bar_base()
        return Markup(c.render_embed())
    
    
    if __name__ == "__main__":
        app.run()

    直接运行,在浏览器中输入地址,直接将数据显示出来了

    这是一个很简单的静态数据展示,别急好戏还在后头~

    Flask 前后端分离

    前面讲的是一个静态数据的展示的方法,用 pyecharts 和  Flask 结合最主要是实现一种动态更新数据,增量更新数据等功能!以上面讲解的内容为基础,在 templates 文件夹中新建一个 index.html 的文件,其中主要用到了 jquery 和 pyecharts 管理的 echarts.min.js 依赖。

    index.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>动态更新数据</title>
        <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
        <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
    </head>
    <body>
        <div id="bar" style="1000px; height:600px;"></div>
        <script>
          (
            function () {
                var result_json = '{{ result_json|tojson }}';
                // var result = JSON.parse(result_json);
                var chart = echarts.init(document.getElementById('bar'), 'gray', {renderer: 'canvas'});
                $.ajax({
                    type: "GET",
                    url: "http://127.0.0.1:5000/barChart",
                    dataType: 'json',
                    data: {result: result_json},
                    success: function (result) {
                        chart.setOption(result);
                    }
                });
            }
        )
        </script>
    </body>
    </html>

    有 html 基础的朋友应该知道该代码主要是向地址 "127.0.0.1:5000/barChart" 发送请求,所以在 app.py 中我们也需要做相应的修改,添加该地址的路由函数,从而实现动态数据更新。
    部分代码如下:

    @app.route("/")
    def index():
        data = request.args.to_dict()
        return render_template("index.html", result_json=data)
    
    @app.route("/barChart")
    def get_bar_chart():
        args = request.args.to_dict()
        result = eval(args.get("result"))
        name = result.get("name")
        subtitle = result.get("subtitle")
        c = bar_base(name, subtitle)
    
        return c.dump_options_with_quotes()

    在 index 视图函数中接收浏览器传过来的参数,然后传递给 index.html。此处只是简单示例,所以未做参数校验。而另一个视图函数主要是获取参数,传给图表生成函数 bar_base(), 从而实现根据 url 地址传过来的参数,动态展示图表数据。结果如下:

    这里只是简单演示, 所以只将图表标题作为动态传参。此场景适用于第一次请求获取我们想要的数据,然后将其展示出来。比如我之前写的 NBA 球员数据可视化

    Python获取NBA历史巨星和现役所有球员生涯数据曲线

    就是此方法,不同球员展示对应球员数据!

    定时全量更新图表

    该场景主要是前端主动向后端进行数据刷新,定时刷新的核心在于 HTML 的 setInterval 方法。那么 index.html 代码就是下面这样的:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Awesome-pyecharts</title>
        <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
        <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
    
    </head>
    <body>
        <div id="bar" style="1000px; height:600px;"></div>
        <script>
            var chart = echarts.init(document.getElementById('bar'), 'white', {renderer: 'canvas'});
    
            $(
                function () {
                    fetchData(chart);
                    setInterval(fetchData, 2000);
                }
            );
    
            function fetchData() {
                $.ajax({
                    type: "GET",
                    url: "http://127.0.0.1:5000/barChart",
                    dataType: 'json',
                    success: function (result) {
                        chart.setOption(result);
                    }
                });
            }
        </script>
    </body>
    </html>

    对应的将 app.py 中 bar_base() 作相应的修改,从而实现定时全量更新图表

    def bar_base() -> Bar:
        c = (
            Bar()
                .add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
                .add_yaxis("商家A", [random.randint(10, 100) for _ in range(6)])
                .add_yaxis("商家B", [random.randint(10, 100) for _ in range(6)])
                .set_global_opts(title_opts=opts.TitleOpts(title="", subtitle=""))
        )
        return c
    
    @app.route("/")
    def index():
        return render_template("index.html")
    
    @app.route("/barChart")
    def get_bar_chart():
        c = bar_base()
        return c.dump_options_with_quotes()

    运行之后,在浏览器中打开,效果如下:

    看到这动图,有没有一种…,如果我是 DJ DJ,琦你太美…

    定时增量更新图表

    同样的要对 index.html 做修改

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Awesome-pyecharts</title>
        <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
        <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
    
    </head>
    <body>
        <div id="bar" style="1000px; height:600px;"></div>
        <script>
            var chart = echarts.init(document.getElementById('bar'), 'white', {renderer: 'canvas'});
            var old_data = [];
            $(
                function () {
                    fetchData(chart);
                    setInterval(getDynamicData, 2000);
                }
            );
    
            function fetchData() {
                $.ajax({
                    type: "GET",
                    url: "http://127.0.0.1:5000/lineChart",
                    dataType: "json",
                    success: function (result) {
                        chart.setOption(result);
                        old_data = chart.getOption().series[0].data;
                    }
                });
            }
    
            function getDynamicData() {
                $.ajax({
                    type: "GET",
                    url: "http://127.0.0.1:5000/lineDynamicData",
                    dataType: "json",
                    success: function (result) {
                        old_data.push([result.name, result.value]);
                        chart.setOption({
                            series: [{data: old_data}]
                        });
                    }
                });
            }
    
        </script>
    </body>
    </html>

    增量更新,后端代码也需要相应的修改

    from pyecharts.charts import Line
    
    def line_base() -> Line:
        line = (
            Line()
            .add_xaxis(["{}".format(i) for i in range(10)])
            .add_yaxis(
                series_name="",
                y_axis=[randrange(50, 80) for _ in range(10)],
                is_smooth=True,
                label_opts=opts.LabelOpts(is_show=False),
            )
            .set_global_opts(
                title_opts=opts.TitleOpts(title="动态数据"),
                xaxis_opts=opts.AxisOpts(type_="value"),
                yaxis_opts=opts.AxisOpts(type_="value"),
            )
        )
        return line
    
    @app.route("/")
    def index():
        return render_template("index.html")
    
    @app.route("/lineChart")
    def get_line_chart():
        c = line_base()
        return c.dump_options_with_quotes()
    
    idx = 9
    
    @app.route("/lineDynamicData")
    def update_line_data():
        global idx
        idx = idx + 1
        return jsonify({"name": idx, "value": randrange(50, 80)})

    走起,来看看效果吧

    作者:华为云合作开发者Jerryning   Python编程与实战

  • 相关阅读:
    最长连续子序列(dp,分而治之递归)
    判断线段是否相交
    1840: Jack Straws
    5065: 最长连续子序列
    TZOJ 4493: Remove Digits
    TZOJ 5271: 质因数的个数
    2019年天梯赛
    PTA 树的遍历
    TZOJ:3660: 家庭关系
    PTA 复数四则运算
  • 原文地址:https://www.cnblogs.com/huaweicloud/p/11861204.html
Copyright © 2011-2022 走看看