【Python使用筆記】——Pyxley 包下的Dashboard開發
阿新 • • 發佈:2019-01-26
by. Zhang.J
本文簡介
本篇將基於Python開源的Pyxley包,從MySQL資料庫讀取資訊,並將資料以線圖(ploty)的形式展示出來。
Pyxley是基於Flask框架開發的開源的Web Dashboard平臺,包下整合多種資料視覺化模組。不用書寫複雜的JS、HTML和CSS就能通過呼叫Python介面實現一個Web應用。官方網站()給出了詳細的說明並給出了一個線圖(ploty)的例子,但由於給的是程式碼段且有部分有Bug,於是我從Github開源站()下載了原始碼包,並對原始碼包中的Example做了解讀。
正文
一、MySQL連線及資料收集
二、Pyxley example 下的 ploty案例解讀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)
1.案例概述
example下的ploty檔案目錄
前文提到Pyxley是基於Flask開發的,所有工程必有兩個核心檔案
__init__.py :初始化應用,需要再此宣告應用目錄,資料來源等核心設定
buildui.py :應用的UI設計,在這裡通過呼叫Flask和Pyxley的介面實現將初始化
類傳來的資料視覺化(下圖為資料預覽)
2.案例程式碼解讀
__init__.py
buildui.pyfrom 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)
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