1. 程式人生 > >【Python使用筆記】——Pyxley 包下的Dashboard開發

【Python使用筆記】——Pyxley 包下的Dashboard開發

by. Zhang.J

本文簡介

本篇將基於Python開源的Pyxley包,從MySQL資料庫讀取資訊,並將資料以線圖(ploty)的形式展示出來。

Pyxley是基於Flask框架開發的開源的Web Dashboard平臺,包下整合多種資料視覺化模組。不用書寫複雜的JS、HTML和CSS就能通過呼叫Python介面實現一個Web應用。官方網站()給出了詳細的說明並給出了一個線圖(ploty)的例子,但由於給的是程式碼段且有部分有Bug,於是我從Github開源站()下載了原始碼包,並對原始碼包中的Example做了解讀。

正文

一、MySQL連線及資料收集

import MySQLdb as mysql
import pandas as pd

# 建立 sql連結
conn = mysql.connect(host="172.17.11.188",user="root",passwd="root",db="wind_analysis")
sql = conn.cursor()
# 獲取表為DataFrame
sql.execute('select FARM_NAME,FAN_TYPE,FAN_NO,DATA_DATE,WIND_SPEED,AC_POWER from pcbin_month')
rows = sql.fetchall()
df = pd.DataFrame([[ij for ij in i] for i in rows])
df.rename(columns={0:'farm',1:'type',2:"no",3:"date",4:"windspeed",5:"power"},inplace=True)
二、Pyxley  example 下的 ploty案例解讀

1.案例概述

example下的ploty檔案目錄

前文提到Pyxley是基於Flask開發的,所有工程必有兩個核心檔案

__init__.py :初始化應用,需要再此宣告應用目錄,資料來源等核心設定

buildui.py  :應用的UI設計,在這裡通過呼叫Flask和Pyxley的介面實現將初始化

類傳來的資料視覺化(下圖為資料預覽)


2.案例程式碼解讀

__init__.py

from os import path
from buildui import get_layouts
from pyxley.utils import create_app, default_static_path, default_template_path

# create the flask app
# #獲取檔案路徑
here = path.abspath(path.dirname(__file__))
# #呼叫Pyxley介面建立應用
app = create_app(here, default_static_path(), default_template_path())

# build the layout
# #呼叫buildui.py的自定義方法,將依賴的應用、資料檔案傳入
get_layouts(app, here+"/fitbit_data.csv")

if __name__ == "__main__":
    app.run(debug=True)
 buildui.py
from pyxley.charts.plotly import PlotlyAPI
from pyxley.filters import SelectButton
from pyxley import UILayout, register_layouts
import pandas as pd

from flask import jsonify, request

def make_ui(filename):
    df = pd.read_csv(filename)

    # Make a UI
    # #新建 UI模板
    ui = UILayout("FilterChart")

    # Read in the data and stack it, so that we can filter on columns
    # 將 Date作為 Index 方便按其餘列拆分
# 實現以Date為X軸
以其他任意列為Y軸 _stack = df.set_index("Date").stack().reset_index() _stack = _stack.rename(columns={"level_1": "Data", 0: "value"}) # Make a Button # 按鈕選項集 cols = [c for c in df.columns if c != "Date"] # SelectButton(按鈕預設填充,標籤元素,標籤別名(底層 API會用),預設選擇) btn = SelectButton("Data", cols, "Data", "Steps") # add the button to the UI # 按鈕置入UI ui.add_filter(btn) # 初始選擇的按鈕 {按鈕名:按鈕某個選項} init_params = {"Data": "Steps"} # 根據按鈕選項調整資料集 返回實現線性介面 def get_data(): args = {} # 呼叫Flask的 request實現獲取頁面選項引數 for c in init_params: if request.args.get(c): args[c] = request.args[c] else: args[c] = init_params[c] return jsonify( # 實現線性介面(輸入的 DF,元組型列值對應的列表,介面型別,屬性引數) PlotlyAPI.line_plot( PlotlyAPI.apply_filters(_stack, args), [("Date", "value")], "lines+markers", {} )) # 建立 plot介面型(ChartId,URL連結,初始化時執行的方法,初始化引數) _plot = PlotlyAPI( "plotly_chart", "/api/plotly_line_plot/", get_data, init_params=init_params ) ui.add_chart(_plot) return ui def get_layouts(mod, filename): # plotly # 呼叫 make_ui(資料檔案) plotly_ui = make_ui(filename) # UI適用於APP(APP) plotly_ui.assign_routes(mod) # 獲取屬性 plotly_props = plotly_ui.build_props() # 建立介面 型別:{UI屬性,標題} _layouts = { "plotly": { "layout": [plotly_props], "title": "Plotly" } } # 返回註冊好的介面 register_layouts(_layouts, mod)
執行__init__.py 進入localhost:5000檢視


3.自己應用

資料預覽


需求簡介:通過選擇FARM_NAME、FAN_TYPE、FAN_NO、DATA_DATE

將對應的WIND_SPEED--AC_POWER圖畫出來。

可以看出,案例給的相當於“一個X對應多個Y,通過Y標籤確定Y”,

但這個需求是“多個屬性確定一組對應的XY”。於是我將問題

轉化為“多個X對應多組Y,通過屬性標籤確認X”

__init__.py

這裡我採用從MySQL資料庫中讀取資料,並直接以Data Frame的格式扔給buildui.py

# -coding:utf-8
from os import path
from buildui import get_layouts
import MySQLdb as mysql
import pandas as pd
from pyxley.utils import create_app, default_static_path, default_template_path

# 建立 Flask 型別APP
# 獲取檔案路徑
here = path.abspath(path.dirname(__file__))
# 建立 APP(專案路徑,預設路徑,預設快取路徑)
app = create_app(here, default_static_path(), default_template_path())

# 建立 sql連結
conn = mysql.connect(host="172.17.11.188",user="root",passwd="root",db="wind_analysis")
sql = conn.cursor()
# 獲取表為DataFrame
sql.execute('select FARM_NAME,FAN_TYPE,FAN_NO,DATA_DATE,WIND_SPEED,AC_POWER from pcbin_month')
rows = sql.fetchall()
df = pd.DataFrame([[ij for ij in i] for i in rows])
df.rename(columns={0:'farm',1:'type',2:"no",3:"date",4:"windspeed",5:"power"},inplace=True)


# 獲取介面(APP,資料檔案)
get_layouts(app, df)

if __name__ == "__main__":
    print here
    app.run(debug=True)
buildui.py
#- coding:utf-8
from pyxley.charts.plotly import PlotlyAPI
from pyxley.filters import SelectButton
from pyxley import UILayout, register_layouts
import pandas as pd
import json

from flask import jsonify, request,session

# 自定義過濾資料矩陣方法,來根據屬性篩選對應的XY,而不使用它自己的Filter
def dataFilter(data,filters):
    rel = data[(data.farm==filters.get("farm"))&
               (data.type==filters.get("type"))&
               (data.no == filters.get("no"))&
               (data.date == filters.get("date"))]
    rel = rel.sort_values(by="windspeed",ascending=True)
    return rel

# 建立 UI 
def make_ui(DF):
    # # # 資料層==============================================================================================
    # 資料讀入
    df = DF
    # 將 Date作為 Index 方便按其餘列拆分 
    # 這裡將X和X的屬性列 測試風場 GW50-750 WT02287 2015-10-01 一起作為Index
    _stack = df.set_index(["windspeed","farm","type","no","date"]).stack().reset_index()
    # 改個名
    _stack = _stack.rename(columns={"level_5": "Data", 0: "value"})

    # # # UI層=================================================================================================
    # 新建 UI模板
    ui = UILayout("FilterChart")

    # # 製作按鈕選項-------------------------------------------------------------------------------------------
    # 按鈕選項集
    cols1 = list(set(_stack.farm))
    cols2 = list(set(_stack.type))
    cols3 = list(set(_stack.no))
    cols4 = list(set(_stack.date))

    # SelectButton(按鈕預設填充,標籤元素,標籤別名(底層 API會用),預設選擇)
    btn1 = SelectButton("風機風場", cols1, "farm", "????")
    btn2 = SelectButton("風機型號", cols2, "type", "GW50-750")
    btn3 = SelectButton("風機編號", cols3, "no", "WT02309")
    btn4 = SelectButton("資料日期", cols4, "date", "201601")

    # 按鈕置入UI
    ui.add_filter(btn1)
    ui.add_filter(btn2)
    ui.add_filter(btn3)
    ui.add_filter(btn4)

    # 初始選擇的按鈕 {按鈕名:按鈕某個選項}
    global params
    params = {"farm": "????", "type": "GW50-750","no":"WT02309","date":"201601"}

    # # 製作線圖-----------------------------------------------------------------------------------------------
    # 根據按鈕選項調整資料集 返回實現線性介面
    def get_data():
        global params
        # 通過收集每次按鈕事件請求,更新整體屬性選擇
        params_in = request.args
        for k in  params_in:
            v = params_in[k]
            params.update({k: v})

        # 返回 json
        return jsonify(
            # 實現線性介面(輸入的 DF,元組型列值對應的列表,介面型別,屬性引數)
            PlotlyAPI.line_plot(
                # (資料集,過濾的{列:值})返回df,而不呼叫它自己的Filter
                dataFilter(_stack, params),
                [("windspeed", "value")],
                "lines+markers",
                {}
            ))

    # 建立 plot介面型(ChartId,URL連結,初始化時執行的方法,初始化引數)
    _plot = PlotlyAPI(
        "plotly_chart",
        "/api/plotly_line_plot/",
        get_data,
        init_params=params
    )
    _plot2 = PlotlyAPI(
        "plotly_chart",
        "/api/plotly_line_plot/",
        get_data,
        init_params=params
    )
    ui.add_chart(_plot)
    ui.add_chart(_plot2)

    # 返回 UI
    return ui

# 主要函式 建立介面(APP 資料檔案)
def get_layouts(mod, DF):

    # 呼叫 make_ui(資料檔案)
    plotly_ui = make_ui(DF)
    # UI適用於APP(APP)
    plotly_ui.assign_routes(mod)
    # 獲取屬性
    plotly_props = plotly_ui.build_props()
    # 建立介面 型別:{UI屬性,標題}
    _layouts = {
        "plotly": {
            "layout": [plotly_props],
            "title": "NEU_LightBuld    Hadoop實驗結果資料演示"
        }
    }
    # 返回註冊好的介面
    register_layouts(_layouts, mod)
結果預覽


反思

對於資料庫極大的可以採用在__init___.py接受請求,直接利用SQLConnector得到需要的部分發給buildui.py

個人學習,歡迎各位大佬指教