1. 程式人生 > 其它 >echarts使用多圖的表達

echarts使用多圖的表達

記錄瞬間

在實際的工作中總會遇到一些報表的展示問題,echarts作為百度的開源工具針對作圖來說是不二選擇。

教程連結:https://echarts.apache.org/zh/tutorial.html#5%20%E5%88%86%E9%92%9F%E4%B8%8A%E6%89%8B%20ECharts

引數設定:https://echarts.apache.org/zh/option.html#title

本文主要介紹使用echarts時關於一批關聯資料,展示到一張圖上的方法

主要應用:flask+bootstrap+echarts

由於使用flask的三方外掛(pyecharts)在靈活處理非圖表資料時較為複雜,所以需要考慮,單獨使用echarts進行考慮

先將flask的pyecharts實現簡單程式碼作以展示

def render_result(data):
    from pyecharts.charts import Bar, Grid, Timeline
    from pyecharts import options as opts
    # 內建主題型別可檢視 pyecharts.globals.ThemeType
    from pyecharts.globals import ThemeType
    from pyecharts.globals import CurrentConfig
    from jinja2 import
Markup, Environment, FileSystemLoader from pyecharts.commons.utils import JsCode # 關於 CurrentConfig,可參考 [基本使用-全域性變數] CurrentConfig.GLOBAL_ENV = Environment(loader=FileSystemLoader("./templates/echarts")) # js程式碼 js_code_str = ''' function(params){ return params.data.text; }
''' all_bar_keys = [] # 獲取所有的key資料 result是從執行結果的資料資訊中獲取的資料,不是最完整的資料結果 for get_data in data: all_bar_keys += data[get_data]['result'].keys() # 去重 get_bar_keys = list(set(all_bar_keys)) # 所有模組名稱去重後的結果 get_bar_keys.sort() # 排序保證每次顯示的結果一致 all_keys = list(data.keys()) # 獲取執行的所有時間區間的值 all_keys.sort(reverse=True) # 按照大小進行排序 bar = ( Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT)) .add_xaxis([i for i in range(1, len(all_keys))]) .set_global_opts(title_opts=opts.TitleOpts(title="結果展示", subtitle="統計當前展示結果"), tooltip_opts=opts.TooltipOpts(formatter=JsCode(js_code_str)), toolbox_opts=opts.ToolboxOpts(is_show=True, feature={"saveAsImage": {}, "dataZoom": {"yAxisIndex": "none"}, "restore": {}, "magicType": {"show": True, "type": ["line", "bar", "stack"]}}) ) ) for bar_key in get_bar_keys: # 遍歷所有的模組資料 get_list = [] # 儲存執行結果中的,未出現模組個數資料,但不是最準確的資料結果 temp_dict = {"value": 0, "text": ""} for data_key in all_keys: # 遍歷所有時間區間,篩選出符合相關模組的query詞 temp_dict["text"] = data_key + "<br>" + bar_key if bar_key in data[data_key]['result']: # 結果是從執行query詞的結果中獲取的,不是最準確的結果,可參考 temp_dict["value"] = len(data[data_key]['result'][bar_key]) get_list.append(copy.deepcopy(temp_dict)) else: temp_dict["value"] = 0 get_list.append(copy.deepcopy(temp_dict)) bar_ = ( Bar() .add_xaxis([i for i in range(1, len(all_keys))]) .add_yaxis(bar_key, get_list) ) bar.overlap(bar_) get_all_order_dict = {} all_bar = [] # 儲存所有模組下的柱狀圖 row_list = [] # 記錄行資料 count = 1 # 遍歷所有模組,每增加一個模組進行 +1 處理 revise = 0 # 資料校正標記 for bar_key in get_bar_keys: # 遍歷所有的模組資料 get_all_order_dict[bar_key] = [] for data_key in all_keys: if bar_key in data[data_key]['result']: for word in data[data_key]['result'][bar_key]: if word not in get_all_order_dict[bar_key]: get_all_order_dict[bar_key].append(word) get_len = len(str(get_all_order_dict[bar_key])) # 獲取所有詞的長度 rows = int(get_len / 85) + 1 # 除以95後,獲取需要分幾行,每行在乘以30就可以獲取到詞位置的高度了 title_pos = 460 + 330 * (count - 1) + revise legend_pos = 510 + 330 * (count - 1) + revise row_list.append(rows) if row_list[count - 1] > 3: revise += (row_list[count - 1] - 3) * 30 print(title_pos, legend_pos, revise) key_bar = ( Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK)) .add_xaxis([i for i in range(1, len(all_keys))]) .set_global_opts(title_opts=opts.TitleOpts(title="關鍵字統計展示-{}".format(bar_key), subtitle="統計當前出現了關鍵字的相關詞展示結果", pos_top="{}px".format(title_pos)), tooltip_opts=opts.TooltipOpts(formatter=JsCode(js_code_str)), legend_opts=opts.LegendOpts(pos_top="{}px".format(legend_pos), is_show=True, selected_mode='single')) # selected_mode 可以使用“single”、“multiple”使用單選或多選模式,預設為multiple ) count += 1 for word in get_all_order_dict[bar_key]: get_keys = [] # 儲存所有模組的對應query詞的個數資料,準確的結果 temp_dict = {"value": 0, "text": ""} for data_key in all_keys: # 遍歷結果資料 temp_dict["text"] = word + '<br>' + data_key + '<br>' + bar_key if bar_key in data[data_key]["keys_order"]: if word in data[data_key]["keys_order"][bar_key]: temp_dict['value'] = 1 get_keys.append(copy.deepcopy(temp_dict)) else: temp_dict['value'] = 0 get_keys.append(copy.deepcopy(temp_dict)) else: temp_dict['value'] = 1 get_keys.append(copy.deepcopy(temp_dict)) key_bar_ = ( Bar() .add_xaxis([i for i in range(1, len(all_keys))]) .add_yaxis(word, get_keys) ) key_bar.overlap(key_bar_) all_bar.append(copy.deepcopy(key_bar)) grid = Grid(init_opts=opts.InitOpts(theme=ThemeType.LIGHT, width='1100px', height='{}px'.format(700+len(row_list)*365))) grid.add(bar, grid_opts=opts.GridOpts(pos_left="5%", pos_right="1%", height="350px")) # grid.add(key_bar, grid_opts=opts.GridOpts(pos_top="520px", pos_left="5%", pos_right="1%", height="30%")) count = 1 # 迴圈展示模組的柱形圖 revise = 0 # 校正資料 for key_bar in all_bar: # grid_pos = 600 + (240 + (sum(row_list[:count])) * 30) * (count - 1) if row_list[count - 1] > 3: revise += (row_list[count - 1] - 3) * 30 grid_pos = 600 + 330 * (count - 1) + revise grid.add(key_bar, grid_opts=opts.GridOpts(pos_top="{}px".format(grid_pos), pos_left="5%", pos_right="1%", height="150px")) count += 1 # return Markup(bar.render_embed()) return grid.render_embed()

方法呼叫如下:

 1 @ots.route('aisi_summary', methods=["GET"])
 2 def aisi_summary():
 3     get_time = get_time_section(96, flag=True)[1]
 4     get_objs = TempData.objects(CREATE_TIME__gte=get_time).all()
 5     if get_objs and len(get_objs) > 85:
 6         data = sfo.aisi_summary()
 7         from jinja2 import Markup
 8         get_render = render_result(data=data)
 9         return Markup(get_render)       # 直接渲染結果
10     else:
11         # 準備資料過程中
12         try:
13             executor.submit(sfo.aisi_summary, flag=True)
14         except:
15             pass
16         return render_template("aisi_summary.html", error="資料修整中,請稍後重試!")

當然使用前提是需要安裝pyecharts,並將pyecharts下面的模板放到templates目錄下,才可以正常展示結果。

此結果是按照既定的pyecharts的模板進行渲染展示的,所以很大程度上無法進行非圖表資料的展示


# 引入echarts

我們希望在展示圖表資料的過程中,還要展示其他的資料,比如:判斷結果,表格,說明等等

過程分為:1、資料準備;2、渲染頁面;3、展示結果

資料準備程式碼

 1 def total_result_for_data(data):
 2     result = {"height": 0, "x": [], "y": [], "title": ['結果概覽'], "count": 0}
 3     all_bar_keys = []
 4     # 獲取所有的key資料  result是從執行結果的資料資訊中獲取的資料,不是最完整的資料結果
 5     for get_data in data:
 6         all_bar_keys += data[get_data]['result'].keys()
 7     # 去重
 8     get_bar_keys = list(set(all_bar_keys))   # 所有模組名稱去重後的結果
 9     get_bar_keys.sort()                      # 排序保證每次顯示的結果一致
10     result['title'] += get_bar_keys          # 主標題設定
11     result['count'] = len(result['title'])   # 記錄顯示的柱形圖的個數
12     all_keys = list(data.keys())             # 獲取執行的所有時間區間的值
13     all_keys.sort(reverse=True)              # 按照大小進行排序
14     result['all_keys'] = all_keys
15     result['x'] = [i for i in range(1, len(all_keys)+1)]   # 生成x軸刻度
16     # 總體資料展示結果
17     get_all_order_dict = {}
18     row_list = []  # 記錄行資料
19     count = 1      # 遍歷所有模組,每增加一個模組進行 +1 處理
20     result['結果概覽_source'] = []
21     result['結果概覽'] = get_bar_keys
22     result['grid_pos'] = [100]
23     for bar_key in get_bar_keys:
24         set_date_key = {"name": bar_key, "type": "bar", "data": [], "label": {"show": "true"}}
25         for data_key in all_keys:           # 遍歷所有時間區間,篩選出符合相關模組的query詞
26             temp_dict = {"value": 0, "text": data_key + '===' + bar_key}
27             get_all_order_dict[bar_key] = []
28             if bar_key in data[data_key]['result']:  # 結果是從執行query詞的結果中獲取的
29                 data_value = len(data[data_key]['result'][bar_key])
30                 temp_dict["value"] = len(data[data_key]['result'][bar_key])
31             else:
32                 temp_dict["value"] = 0
33                 data_value = 0
34             set_date_key["data"].append(copy.deepcopy(temp_dict))
35             if bar_key in data[data_key]['result']:
36                 for word in data[data_key]['result'][bar_key]:
37                     if word not in get_all_order_dict[bar_key]:
38                         get_all_order_dict[bar_key].append(word)
39         result['結果概覽_source'].append(copy.deepcopy(set_date_key))
40     print(result['結果概覽_source'])
41     for bar_key in get_bar_keys:            # 遍歷所有的模組資料
42         result[bar_key + "_source"] = []
43         get_all_order_dict[bar_key] = []
44         for data_key in all_keys:           # 遍歷所有時間區間,篩選出符合相關模組的query詞
45             if bar_key in data[data_key]['result']:
46                 for word in data[data_key]['result'][bar_key]:
47                     if word not in get_all_order_dict[bar_key]:
48                         get_all_order_dict[bar_key].append(word)
49         result[bar_key] = copy.deepcopy(get_all_order_dict[bar_key])
50 
51         get_len = len(str(get_all_order_dict[bar_key]))  # 獲取所有詞的長度
52         rows = int(get_len / 85) + 1            # 除以85後,獲取需要分幾行,每行在乘以30就可以獲取到詞位置的高度了
53 
54         result['grid_pos'].append(70 + 30 * rows)
55 
56         count += 1
57         for word in get_all_order_dict[bar_key]:
58             set_date_key = {"name": word, "type": "bar", "data": [], "label": {"show": "true"}}
59             for data_key in all_keys:  # 遍歷結果資料
60                 temp_dict = {"value": 0, "text": word + '===' + data_key + '===' + bar_key}
61                 if bar_key in data[data_key]["keys_order"]:
62                     if word in data[data_key]["keys_order"][bar_key]:
63                         temp_dict["value"] = 1
64                     else:
65                         temp_dict["value"] = 0
66                 else:
67                     temp_dict["value"] = 1
68                 set_date_key["data"].append(copy.deepcopy(temp_dict))
69             result[bar_key + "_source"].append(copy.deepcopy(set_date_key))
70         print(result[bar_key + "_source"])
71 
72     result['height'] = (len(row_list) + 1) * 365
73 
74     return result

前端程式碼如下

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5 
  6     <meta name="viewport" content="width=device-width, initial-scale=1">
  7     <meta name="description" content="">
  8     <meta name="generator" content="Hugo 0.84.0">
  9     <title>資料分析</title>
 10     <link href="{{ url_for('static', filename='bs/css/bootstrap.min.css') }}" rel="stylesheet">
 11     <link href="{{ url_for('static', filename='bs/css/carousel.css') }}" rel="stylesheet">
 12     <!-- 引入echarts -->
 13     <script src="/static/js/echarts.min.js"></script>
 14 </head>
 15 <body>
 16 {% include "common/header.html" %}
 17 
 18 <div class="container">
 19     <main>
 20         <div style="margin-top:25px">
 21             <nav aria-label="breadcrumb">
 22               <ol class="breadcrumb">
 23                 <li class="breadcrumb-item"><a href="#">監控</a></li>
 24                 <li class="breadcrumb-item active" aria-current="page">資料分析</li>
 25               </ol>
 26             </nav>
 27         </div>
 28     <div class="px-4 py-5 my-5 text-left">
 29         {% if error %}
 30         <span style="color: #e4393c">{{ error }}</span>
 31         {% endif %}
 32     <table class="table table-hover">
 33         <tr><th style="text-align: center;font-size: 0.8cm;background-color: #c8e0cf">結果一覽</th></tr>
 34         <tr>
 35             <td>
 36                 <div id="main_picture"></div>
 37             </td>
 38         </tr>
 39         {% for foo in range(data.count) %}
 40         <tr>
 41             <td>
 42                 <div id="main_picture_{{ foo }}"></div>
 43             </td>
 44         </tr>
 45         {% endfor %}
 46     </table>
 47 
 48     </div>
 49     </main>
 50 </div>
 51 
 52 {% include "common/footer.html" %}
 53 
 54 <script src="/static/bs/js/bootstrap.bundle.min.js"></script>
 55 
 56 <script type="text/javascript">
 57     let temp_str = "{{ data }}".replace(/&#39;/g, '"');
 58     // 將接受的資料轉換為json物件
 59     let obj = eval("("+temp_str+")");
 60     {% if data %}
 61         init(obj);
 62     {% endif %}
 63 
 64     function init(obj){
 65         console.log(obj);
 66         let num = obj.count;
 67         let xdata = obj.x;
 68         let title_data = obj.title;
 69         let grid_pos = obj.grid_pos
 70         for (let mpnum=0; mpnum<num; mpnum++){
 71             let main_picture = document.getElementById('main_picture_' + mpnum);
 72             //計算所需要的高度
 73             if (mpnum === 0) {
 74                 main_picture.style.height = "440px";
 75             } else {
 76                 main_picture.style.height = 150 + grid_pos[mpnum] + "px";
 77             }
 78             // 基於準備好的dom,初始化echarts例項
 79             let myChart = echarts.init(main_picture);
 80             let toolbox = [];      // 設定
 81             let legend = [];       // 圖例顯示
 82 
 83             //通過配置xAxi和yAxis的gridIndex  series的xAxisIndex和yAxisIndex 來配套格子
 84             let option = {
 85                 title: {
 86                       textAlign: "left",
 87                       text: title_data[mpnum],
 88                       subtext: title_data[mpnum],
 89                       top: "0px"
 90                 },
 91                 xAxis: {
 92                     type: "category",
 93                     data: xdata
 94                 },
 95                 yAxis: {
 96                   type: "value",
 97                   inverse: false,
 98                   splitLine: {
 99                     show: true
100                   }
101                 },
102                 series: obj[title_data[mpnum]+"_source"],
103                 grid: {
104                     left: "3%",
105                     right: "1%",
106                     width: "95%",
107                     top: grid_pos[mpnum] + "px"
108                 }
109             };
110             // 工具欄設定
111             if (mpnum === 0) {
112                 toolbox.push({
113                     show: true,
114                     feature: {
115                         mark: {show: true},
116                         dataZoom: {show: true},
117                         dataView: {show: true,readOnly: false},
118                         magicType: {show: true,type: ['line', 'bar', 'stack']},
119                         restore: {show: true},
120                         saveAsImage: {show: true}
121                     }
122                 });
123             } else {
124                 toolbox.push({
125                     show: false
126                 });
127             }
128             option["toolbox"] = toolbox[0];
129             option["tooltip"] = {
130                 position: "top",
131                 formatter: function (params) {
132                     return params.data.text.replace(/===/g, "<br>");
133                 }
134             };
135 
136             // 圖例設定
137             if (mpnum === 0){
138                 legend.push({
139                     selectedMode: 'multiple',
140                     top: "60px",
141                     show: true
142                 });
143             } else {
144                 legend.push({
145                     selectedMode: 'single',
146                     top: "60px",
147                     show: true
148                });
149             }
150             option["legend"] = legend[0];
151             // 使用剛指定的配置項和資料顯示圖表。
152             myChart.setOption(option);
153         }
154     }
155 </script>
156 </body>
157 </html>

展示結果如圖

當然圖表都是動態載入的,整圖下面還有其他的圖表,由於截圖關係只擷取當前兩張

注意:當前使用的都是最新的版本(bootstrap-v5.0、echarts-5.1.2)


供參考---結束了

===