<font color=purple face=华文行楷 size="5">"柳丝榆荚自芳菲,不管桃飘与李飞;"
1、简介
A Python Echarts Plotting Library. Apache Echarts 是一个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可。而 Python 是一门富有表达力的语言,很适合用于数据处理。当数据分析遇上数据可视化时,pyecharts 诞生了。
2、Flask + pyecharts
如何在 Flask 中使用 pyecharts。
2.1 Flask 模板渲染
$ mkdir pyecharts-flask-demo
$ cd pyecharts-flask-demo
$ mkdir templates
将 pyecharts 模板,位于 pyecharts.render.templates 拷贝至刚新建的 templates 文件夹。
- server.py
from flask import Flask
from jinja2 import Environment, FileSystemLoader
from pyecharts.globals import CurrentConfig
from markupsafe import Markup
# 关于 CurrentConfig,可参考 [基本使用-全局变量]
CurrentConfig.GLOBAL_ENV = Environment(loader=FileSystemLoader("./templates"))
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()
2.2 Flask 前后端分离
前后端分离可以使用动态更新数据,增量更新数据等功能。
新建一个 HTML 文件。 新建 HTML 文件保存位于项目根目录的 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 style="width: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>
- app.py:
from random import randrange
from flask import Flask, render_template
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", [randrange(0, 100) for _ in range(6)])
.add_yaxis("商家B", [randrange(0, 100) for _ in range(6)])
.set_global_opts(title_opts=opts.TitleOpts(title="Bar-基本示例", 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()
if __name__ == "__main__":
app.run()
2.3 定时全量更新图表
前端主动向后端进行数据刷新 定时刷新的核心在于 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 style="width: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: 代码同上。
2.4 定时增量更新图表
- 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 style="width: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>
- app.py:
from random import randrange
from flask.json import jsonify
from flask import Flask, render_template
from pyecharts import options as opts
from pyecharts.charts import Line
app = Flask(__name__, static_folder="templates")
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)})
if __name__ == "__main__":
app.run()
3、Flask + echarts.js
3.1 直接渲染
- app.py:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
- index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>第一个 ECharts 实例</title>
<!-- 引入 echarts.js -->
<script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js"></script>
</head>
<body>
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var option = {
legend: {},
tooltip: {},
dataset: {
source: [
['product', '2012', '2013', '2014', '2015'],
['Matcha Latte', 41.1, 30.4, 65.1, 53.3],
['Milk Tea', 86.5, 92.1, 85.7, 83.1],
['Cheese Cocoa', 24.1, 67.2, 79.5, 86.4]
]
},
xAxis: [
{type: 'category', gridIndex: 0},
{type: 'category', gridIndex: 1}
],
yAxis: [
{gridIndex: 0},
{gridIndex: 1}
],
grid: [
{bottom: '55%'},
{top: '55%'}
],
series: [
// 这几个系列会在第一个直角坐标系中,每个系列对应到 dataset 的每一行。
{type: 'bar', seriesLayoutBy: 'row'},
{type: 'bar', seriesLayoutBy: 'row'},
{type: 'bar', seriesLayoutBy: 'row'},
// 这几个系列会在第二个直角坐标系中,每个系列对应到 dataset 的每一列。
{type: 'bar', xAxisIndex: 1, yAxisIndex: 1},
{type: 'bar', xAxisIndex: 1, yAxisIndex: 1},
{type: 'bar', xAxisIndex: 1, yAxisIndex: 1},
{type: 'bar', xAxisIndex: 1, yAxisIndex: 1}
]
}
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>
3.2 模板渲染
例子: 模板
- app.py:
import pandas as pd
from flask import Flask, render_template
datas = {}
datas2 = {}
df = pd.read_csv('data/datum_shift.csv')
df = df.sort_values('AREA_SOUTH_BOUND_LAT', ascending=False)
for item in df.head().values:
datas[item[0]] = item[1]
datas2[item[0]] = item[2]
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html', datas=datas)
if __name__ == '__main__':
app.run(debug=True)
- index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>房源占比前五的饼图</title>
<script src="./static/js/echarts.min.js"></script>
</head>
<body>
<div style="width:1000px;height:400px"></div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
option = {
title: {
text: 'datum_shift',
subtext: '饼图练习',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
name: '各项占比',
type: 'pie',
radius: '50%',
data: [
{% for data in datas %}
{value:{{ datas[data] }}, name: '{{data}}'},
{% endfor %}
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>
3.3 异步请求$.ajax
例子:$.ajax
创建目录如下:
- test_flask.py:
import json
from flask import Flask, request, jsonify,render_template
app = Flask(__name__)
@app.route('/test')
def hello_world():
return 'Hello World,爱看书的小沐!'
@app.route("/")
def index():
return render_template("index.html")
@app.route('/getdata_bar')
def getdata_bar():
language = ['python', 'java', 'c', 'c++', 'c#', 'php']
value = ['100', '150', '100', '90', '80', '90']
return json.dumps({'language':language,'value':value},ensure_ascii=False)
@app.route('/getdata_pie')
def getdata_pie():
data = [
{"value": 235, "name": '视频广告'},
{"value": 274, "name": '联盟广告'},
{"value": 310, "name": '邮件营销'},
{"value": 335, "name": '直接访问'},
{"value": 400, "name": '搜索引擎'},
{"value": 90, "name": '其他'},
],
return json.dumps({'data':data},ensure_ascii=False)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=8080)
- index.html:
<head>
<meta charset="UTF-8">
<title>Echarts</title>
<script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
<script src="/static/js/echarts.min.js"></script>
<style>
body {
margin: 100px;
}
.flex-div{
display: flex;
width: auto;
}
</style>
</head>
<body>
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div class="flex-div">
<div style="width: 600px;height:400px;"></div>
<div style="width: 600px;height:400px;"></div>
<script type="text/javascript">
$(function () {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('echarts_lang'));
$.ajax({
url:'/getdata_bar',
success:function (data) {
json_data=JSON.parse(data)
console.info(json_data['language'])
console.info(json_data['value'])
var option = {
title: {
text: '人数统计'
},
tooltip: {},
legend: {
data:['2022年销量']
},
xAxis: {
data: json_data['language']
},
yAxis: {},
series: [{
name: '2022年销量',
type: 'bar',
data: json_data['value']
}]
};
myChart.setOption(option);
}
})
})
$(function () {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('echarts_ad'));
$.ajax({
url:'/getdata_pie',
success:function (data) {
json_data=JSON.parse(data)
console.info(json_data['data'])
option = {
series : [
{
name: '访问来源',
type: 'pie',
radius: '55%',
data: json_data['data'][0],
roseType: 'angle',
itemStyle: {
normal: {
shadowBlur: 200,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
],
};
console.info(option)
myChart.setOption(option);
}
})
})
</script>
</body>
3.4 异步请求$.get
例子2: $.get
- app.py:
from flask import Flask, request, jsonify,render_template
app = Flask(__name__)
categories=["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
data=[5, 20, 36, 10, 10, 20]
data2=[111, 222, 80, 150, 75, 55]
app = Flask (__name__)
@app.route('/test')
def hello_world():
return 'Hello World,爱看书的小沐!'
@app.route('/', methods=["GET"])
def index():
return render_template("index.html")
@app.route('/echarts', methods=["GET"])
def echarts():
return jsonify(categories = categories,data = data, data2 = data2)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=8080)
- index.html:
<!DOCTYPE html>
<html style="height: 100%" lang="en">
<head>
<meta charset="utf-8">
<title>My Finance</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
<script src="https://cdn.staticfile.org/echarts/4.8.0/echarts.min.js"></script>
<!-- 引入 vintage 主题 -->
</head>
<body>
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div style="width:1000px;height:300px;"></div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
myChart.setOption({
title: {
text: '$.get异步数据加载示例(爱看书的小沐)'
},
tooltip: {},
legend: {
data: ['1月销量', '2月销量']
},
xAxis: {
data: []
},
yAxis: {},
series: [{
name: '1月销量',
type: 'bar',
data: []
},{
name: '2月销量',
type: 'bar',
data: []
}]
});
// 异步加载数据
$.get('/echarts').done(function (data) {
// 填入数据
myChart.setOption({
xAxis: {
data: data.categories
},
axisLabel: {
show: true,
interval: 0,
rotate: 40,
textStyle: {
color: '#333'
}
},
series: [
{
name: '1月销量',
data: data.data
},
{
name: '2月销量',
data: data.data2
}
]
});
});
myChart.setOption(option);
</script>
</body>
</html>
3.5 Flask + nodejs + vue
对于 Vue 3,你应该使用 npm 上可用的 Vue CLI v4.5 作为 @vue/cli。要升级,你应该需要全局重新安装最新版本的 @vue/cli:
# 全局安装 vue-cli
yarn global add @vue/cli
# 或
cnpm install -g @vue/cli
安装完后查看版本:
$ vue --version
然后在 Vue 项目中运行:
vue upgrade --next
vue create、vue ui、vue init三种方式创建Vue项目。
vue create命令是vue-cli3.x提供创建Vue项目的方式,模板是固定的,模板选项可*配置。 vue ui命令也是vue-cli3.x提供创建Vue项目的方式,可以通过操作可视化页面来创建和管理Vue项目。 vue init命令是vue-cli2.x提供创建Vue项目的方式,可以使用github上面的一些模板来初始化项目。比如webpack就是官方推荐的标准模板。
创建项目:
vue init webpack vue3-test
cd vue3-test
npm run dev
访问网址:http://localhost:8080
npm install --save echarts vue-jsonp vue-resource
- D:\0627\vue3-test\src\main.js:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App.vue'
import VueResource from 'vue-resource'
import * as VueJsonp from 'vue-jsonp'
// import echarts from 'echarts'
import * as echarts from 'echarts';
Vue.use(VueJsonp)
Vue.use(VueResource)
Vue.prototype.$echarts = echarts
new Vue({
el: '#app',
render: h => h(App)
})
- D:\0627\vue3-test\src\App.vue:
<template>
<div class="main">
<chart1 />
</div>
</template>
<script>
import chart1 from "./components/chart1.vue";
export default {
components: {
chart1,
},
};
</script>
- D:\0627\vue3-test\src\components\chart1.vue:
<template>
<div>
<div style="width: 100%; height: 500px"></div>
</div>
</template>
<script>
export default {
name: "chart1",
data() {
return {};
},
methods: {
draw() {
var myChart = this.$echarts.init(
document.getElementById("echartContainer"),
"infographic"
);
myChart.setOption({
xAxis: {},
yAxis: {},
series: [
{
symbolSize: 5,
data: [],
type: "bar",
},
],
});
this.$http
.get("http://localhost:5000/api/demo/", {
headers: { "Access-Control-Allow-Origin": "*" },
})
.then((res) => {
console.log(res.data);
myChart.hideLoading();
myChart.setOption({ series: [{ data: res.data.product }] });
});
},
},
mounted() {
this.draw();
},
};
</script>
<style></style>
- test_flask:
from flask import Flask, jsonify, render_template
from flask.helpers import make_response
from flask_cors import CORS
app = Flask(__name__,
static_folder='./dist', #设置静态文件夹目录
template_folder = "./dist",
static_url_path="") #设置vue编译输出目录dist文件夹,为Flask模板文件目录
CORS(app, resources=r'/*')
@app.route('/', methods=["GET"])
def index():
return render_template("index.html")
@app.route('/api/demo/')
def api_test():
ans = jsonify({
"product": [5, 20, 36, 10, 10, 20]
})
return make_response(ans)
if __name__ == '__main__':
app.run(debug=True)
cd vue3-test
npm run build
npm run dev
访问:http://localhost:8080/ 以上是开启了两个web服务器(Flask、nodejs). 以下是开一个web服务器(Flask)的方法: 将上面打包的dist文件复制到Flask的主文件夹里,然后运行test_flask.py如下。
结语
如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;
╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地
//(ㄒoㄒ)//,就在评论处留言,作者继续改进;
o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;
(✿◡‿◡)
感谢各位大佬童鞋们的支持!
( ´ ▽´ )ノ ( ´ ▽´)っ!!!
<font color=purple face=华文行楷 size="5">"侬今葬花人笑痴,他年葬侬知是谁?"