基于flask的一个数据展示网页

ops/2025/3/11 3:19:53/

前言

开发语言:python3.11.6、javascript、html5‘、css3

开发框架:flask、plotly.js

开发系统:windows10 22H2

开发编辑器:vscode

作用:展示水产养殖水体氨氮和亚硝酸盐时间序列数据,使用LWLR、ESE、DLM模型进行滚动预测并绘制曲线

开发初衷:为了项目汇报更具象

开源性质:完全开源,任意使用

项目资源获取https://pan.baidu.com/s/1V53DPLVP7FT65-FtYVP44Q?pwd=1sdthttps://pan.baidu.com/s/1V53DPLVP7FT65-FtYVP44Q?pwd=1sdt

文件目录展示

图表展示static氨氮预测.xlsxplotly-2.2.0.min.jstemplateses.htmlindex.htmllwlr.htmlrw.htmlmain.py

效果展示

代码说明

基于flask的一个数据展示网页

main.py

导包

python">from flask import Flask,render_template,request,jsonify
import pandas as pd
import numpy as np
from statsmodels.tsa.holtwinters import SimpleExpSmoothing
from scipy.signal import savgol_filter
from werkzeug.datastructures import ImmutableMultiDict

全局变量

python">app=Flask(__name__)
excel_path='./static/氨氮预测.xlsx'

程序启动入口

python">if __name__=='__main__':app.run(debug=True,port=5002,host='0.0.0.0')

html页面响应函数

python">@app.route('/',methods=['GET'])
def index():return render_template('index.html')
@app.route('/lwlr',methods=['GET'])
def page_lwlr():return render_template('lwlr.html')@app.route('/es',methods=['GET'])
def es():return render_template('es.html')@app.route('/rw',methods=['GET'])
def rw():return render_template('rw.html')

excel文件打开函数

python">def open_excel(form_data,key1='sheetname',key2='NH3-NO2'):sheet_index=form_data[key1]column_name=form_data[key2]df=pd.read_excel(excel_path,f'Sheet{sheet_index}').dropna()return df['DATE'].tolist(),df[column_name].tolist()

index.html表单数据处理函数

python">@app.route('/submit',methods=['POST'])
def submit():# 获取表单数据form_data=request.form# 表单数据严格匹配审查if not isinstance(form_data, ImmutableMultiDict):return jsonify({"error": "Invalid form data format"}), 400if 'sheetname' not in form_data:return jsonify({"error": "Invalid form data format"}), 400if 'NH3-NO2' not in form_data:return jsonify({"error": "Invalid form data format"}), 400# 根据表单数据打开对应exceldate,y=open_excel(form_data)# 返回时间序列数据return jsonify({'date':date,'y':y})

lwlr.html表单数据处理函数

python"># lwlr数学定义
def lwlr(test_point,X,y,k):m = X.shape[0]weights = np.eye(m)for i in range(m):xi = X[i]weights[i, i] = np.exp(np.dot((xi - test_point), (xi - test_point).T) / (-2.0 * k**2))X_T = X.TW = weightsbeta = np.linalg.inv(X_T @ (W @ X)) @ (X_T @ (W @ y))return test_point @ beta@app.route('/submit_lwlr',methods=['POST'])
def submit_lwlr():# 获取表单数据form_data=request.form# 表单数据严格匹配审查if not isinstance(form_data, ImmutableMultiDict):return jsonify({"error": "Invalid form data format"}), 400if 'sheetname' not in form_data:return jsonify({"error": "Invalid form data format"}), 400if 'NH3-NO2' not in form_data:return jsonify({"error": "Invalid form data format"}), 400if 'k' not in form_data:return jsonify({"error": "Invalid form data format"}), 400# 根据表单数据打开对应exceldate,y=open_excel(form_data)# 适当转化便于后续匹配k=float(form_data['k'])x=np.arange(len(date)).reshape(-1,1)# 滚动预测y_preds=[]for i in range(2,x.shape[0]+1):X_pred=np.array([i]).reshape(-1,1)y_pred=[lwlr(test_point, x[:i], y[:i], k) for test_point in X_pred]y_preds.append(y_pred[0])# 根据需要可保留至小数2位y_preds=[round(x,2) for x in y_preds]# 返回原始数据和预测数据return jsonify({"date":date,"y1":y,"y2":y_preds})

es.html表单数据处理函数

python"># 平滑滤波
def exponential_smoothing(series, alpha=0.5):"""series: 时间序列数据alpha: 平滑系数"""result = [series[0]]  # 第一项为序列的第一值for n in range(1, len(series)):result.append(alpha * series[n] + (1 - alpha) * result[n-1])return result@app.route('/submit_es',methods=['POST'])
def submit_es():# 获取表单数据form_data=request.form# 表单数据严格匹配审查if not isinstance(form_data, ImmutableMultiDict):return jsonify({"error": "Invalid form data format"}), 400if 'sheetname' not in form_data:return jsonify({"error": "Invalid form data format"}), 400if 'NH3-NO2' not in form_data:return jsonify({"error": "Invalid form data format"}), 400if 'k' not in form_data:return jsonify({"error": "Invalid form data format"}), 400k=float(form_data['k'])if k<0.01 or k>0.99:return jsonify({"error": "Invalid form data format"}), 400# 根据表单数据打开对应exceldate,y=open_excel(form_data)# 进行滚动预测y_preds=exponential_smoothing(y,k)# 根据需要可保留至小数2位y_preds=[round(x,2) for x in y_preds]# 返回原始数据和预测数据return jsonify({"date":date,"y1":y,"y2":y_preds})

rw.html表单数据处理函数

python">@app.route('/submit_rwsg',methods=['POST'])
def submit_rwsg():# 获取表单数据form_data=request.form# 表单数据严格匹配审查if not isinstance(form_data, ImmutableMultiDict):return jsonify({"error": "Invalid form data format"}), 400if 'sheetname' not in form_data:return jsonify({"error": "Invalid form data format"}), 400if 'NH3-NO2' not in form_data:return jsonify({"error": "Invalid form data format"}), 400if 'k1' not in form_data:return jsonify({"error": "Invalid form data format"}), 400if 'k2' not in form_data:return jsonify({"error": "Invalid form data format"}), 400# 适当转化便于后续匹配k1=int(form_data['k1'])k2=int(form_data['k2'])# 表单数据严格审查if k1<=k2:return jsonify({"error": "Invalid form data format"}), 400if k1>=len(date):return jsonify({"error": "Invalid form data format"}), 400# 根据表单数据打开对应exceldate,y=open_excel(form_data)# 对原始数据进行SG滤波y=savgol_filter(res, window_length=k1, polyorder=k2)# 滚动预测res=[]for i in range(2,len(y)+1):model = SimpleExpSmoothing(y[:i])fit = model.fit()# 预测未来1天forecast = fit.forecast(1)[0]res.append(forecast)# 对模型输出进行极小值抑制res=[x if x>=0.05 else 0.05 for x in res ]y_preds=res.tolist()# 根据需要可保留至小数2位y_preds=[round(x,2) for x in y_preds]# 返回原始数据和预测数据return jsonify({"date":date,"y1":y,"y2":y_preds})

index.html

整体框架

<body><nav><a href="/">数据集</a><a href="/lwlr">LWLR</a><a href="/es">ES</a><a href="/rw">RWSG</a></nav><header><form><select></select><select></select><button></button></form><button><botton></header><main><section><table id="table"></table></section><section><div id="plot"></div></section></main>

动画

@keyframes bottomIn{from {transform: translateY(4dvh);}to {transform: translateY(0);opacity: 1;}}@keyframes topIn{from {transform: translateY(-4dvh);}to {transform: translateY(0);opacity: 1;}}@keyframes rightIn{from {transform: translateX(30vw);}to {transform: translateX(0);opacity: 1;}}@keyframes leftIn{from {transform: translateX(-30vw);}to {transform: translateX(0);opacity: 1;}}nav{opacity: 0;animation: 1.1s topIn ease-out forwards;animation-delay: 0.3s;}header{opacity: 0;animation: 1s topIn ease-out forwards;animation-delay: 0.2s;}#left{opacity: 0;animation: 1.1s leftIn ease-out forwards;animation-delay: 0.3s;}#right{opacity: 0;animation: 1.1s rightIn ease-out forwards;animation-delay: 0.3s;}

背景切换

用全局css变量定义各模块的前景色和背景色,点击背景切换按钮则触发js把变量的值相互替换

/*css*/
a:hover,button:hover,select:hover{transform: scale(1.1);text-shadow: 0 0 3vw var(--f-color);box-shadow: 0 0 3vw var(--f-color);}
select{appearance: none;color: var(--f-color);background: var(--b-color);width: 8vw;height: 4dvh;border: 1px solid var(--f-color);border-radius: 1dvh;padding-left: 1vw;}
:root{--f-color:#cccccc;--b-color:#333333;}
/*js*/
function changeTheme(){const root=document.documentElementconst color1=window.getComputedStyle(root).getPropertyValue('--f-color').trim()const color2=window.getComputedStyle(root).getPropertyValue('--b-color').trim()root.style.setProperty('--f-color',color2)root.style.setProperty('--b-color',color1)}

响应式布局

所有模块大小使用相对视口尺寸定义

select{appearance: none;color: var(--f-color);background: var(--b-color);width: 8vw;height: 4dvh;border: 1px solid var(--f-color);border-radius: 1dvh;padding-left: 1vw;}

鼠标浮动光影

a:hover,button:hover,select:hover{transform: scale(1.1);text-shadow: 0 0 3vw var(--f-color);box-shadow: 0 0 3vw var(--f-color);}

异步表单提交

async function submitForm(event){event.preventDefault()const submitButton = event.target.querySelector('button[type="submit"]')submitButton.disabled = trueconst formData=new FormData(event.target)try{const response=await fetch('/submit',{method:'POST',body:formData})if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}const data = await response.json()createTable(data)createPlot(data)}catch(error){console.error('Error submitting form:', error);alert('非法输入')}finally{submitButton.disabled = false}}

表格绘制函数

function createTable(data){const table=document.getElementById('table')table.innerHTML=''const thead=document.createElement('thead')const tr=document.createElement('tr')const th1=document.createElement('th')const th2=document.createElement('th')const tbody=document.createElement('tbody')th1.textContent='时间'tr.appendChild(th1)th2.textContent='index'tr.appendChild(th2)thead.appendChild(tr)table.appendChild(thead)for(let i=0;i<data.date.length;i++){const tr=document.createElement('tr')const td1=document.createElement('td')const td2=document.createElement('td')td1.textContent=data.date[i]tr.appendChild(td1)td2.textContent=data.y[i]tr.appendChild(td2)tbody.appendChild(tr)}table.appendChild(tbody)}

图像数据绘制

function createPlot(data){const y=data.yconst x=Array.from({length:y.length},(_,index)=>index)const traces=[{x,y,mode: "lines",type: "scatter"}]const layout={xaxis:{title:'时间',titlefont: {color: 'green',size:20},tickfont: {color: 'green',size:20}},yaxis:{title:'index',titlefont: {color: 'green',size:20},tickfont: {color: 'green',size:20}},paper_bgcolor: 'rgba(0,0,0,0)',plot_bgcolor: 'rgba(0,0,0,0)'}Plotly.newPlot("plot",traces,layout)}

其他html

与index.html基本相同,主要区别在画图

function createPlot(data){data.y1.pop()data.y2.shift()data.y2.shift()const y1=data.y1const x1=Array.from({ length: y1.length }, (_, index) => index)const y2=data.y2const x2=Array.from({ length: y2.length }, (_, index) => index+2)const trace1={x:x1,y:y1,name:'True',mode: "lines",type: "scatter"}const trace2={x:x2,y:y2,name:'lwlr-predict',mode: "lines",type: "scatter"}const y1y2=[trace1,trace2]const layout={xaxis:{title:'时间',titlefont: {color: 'green',size:20},tickfont: {color: 'green',size:20}},yaxis:{title:'index',titlefont: {color: 'green',size:20},tickfont: {color: 'green',size:20}},legend:{font:{color:'green',size:20}},showlegend:true,paper_bgcolor: 'rgba(0,0,0,0)',plot_bgcolor: 'rgba(0,0,0,0)'}Plotly.newPlot("plot",y1y2,layout)}

绘表

            function createTable(data){const table=document.getElementById('table')table.innerHTML=''const thead=document.createElement('thead')const tr=document.createElement('tr')const th1=document.createElement('th')const th2=document.createElement('th')const th3=document.createElement('th')const tbody=document.createElement('tbody')th1.textContent='时间'tr.appendChild(th1)th2.textContent='index'tr.appendChild(th2)th3.textContent='预测值'tr.appendChild(th3)thead.appendChild(tr)table.appendChild(thead)let lastDateStr = data.date[data.date.length-1]let lastDate = new Date(lastDateStr)lastDate.setDate(lastDate.getDate() + 1);let newDateStr = lastDate.toISOString().split('T')[0];data.date.push(newDateStr);data.y1.push(null)data.y2.unshift(null)data.y2.unshift(null)for(let i=0;i<data.y1.length;i++){const tr=document.createElement('tr')const td1=document.createElement('td')const td2=document.createElement('td')const td3=document.createElement('td')td1.textContent=data.date[i]tr.appendChild(td1)td2.textContent=data.y1[i]tr.appendChild(td2)td3.textContent=data.y2[i]tr.appendChild(td3)tbody.appendChild(tr)}table.appendChild(tbody)}


http://www.ppmy.cn/ops/164828.html

相关文章

基于SpringBoot的历史馆藏系统设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

Linux驱动学习之平台总线设备树驱动模型

0.步骤零&#xff1a;通用操作指针变量 static int major 0; //主设备号 static struct class *sr501_class; //定义类 static struct gpio_desc *sr501_gpio; //GPIO结构体操作指针 static int sr501_irq; …

Manus邀请码获取方法 + 使用指南(直接领取pdf)

昨天发布消息通用AI智能体 Manus今天彻底火了&#xff0c;大家估计还在找邀请码吧。 本人已注册成功&#xff0c;Manus邀请码获取方法 使用指南的pdf 无套路分享给大家。 邀请码获取方法 ✅ https://pan.quark.cn/s/5e062d19e7cf Manus界面预览

Java 中操作 R:深度整合与高效应用

Java 中操作 R:深度整合与高效应用 引言 随着大数据和机器学习的快速发展,R 语言在数据分析和可视化方面扮演着越来越重要的角色。而 Java 作为一种广泛应用于企业级应用开发的语言,其强大的功能和稳定性使其成为构建高性能应用的首选。本文将探讨 Java 如何操作 R 语言,…

物联网中如何解决网络复杂性的问题

物联网(IoT)中的网络复杂性问题是物联网系统设计和运维中的一大挑战。网络复杂性可能源于多种因素,包括设备数量庞大、通信协议多样、网络拓扑复杂、数据流量巨大、安全性和隐私保护需求高等。解决网络复杂性问题是确保物联网系统高效、可靠和安全运行的关键。以下是一些解决…

sqli-lab靶场学习(七)——Less23-25(关键字被过滤、二次注入)

前言 之前的每一关&#xff0c;我们都是在末尾加上注释符&#xff0c;屏蔽后面的语句&#xff0c;这样我们只要闭合了区间之后&#xff0c;差不多就是为所欲为的状态。但如果注释符不生效的情况下&#xff0c;又该如何呢&#xff1f; Less23&#xff08;注释符被过滤&#xff…

在ubuntu20.4中如何创建一个虚拟环境(亲测有效)

步骤 1&#xff1a;安装 virtualenv 和 virtualenvwrapper 更新包列表&#xff1a; sudo apt update安装 virtualenv 和 virtualenvwrapper&#xff1a; sudo apt install python3-virtualenv python3-virtualenvwrapper步骤 2&#xff1a;配置 virtualenvwrapper 你需要将…

梯度计算中常用的矩阵微积分公式

标量对向量求导的常用数学公式 设标量函数 y f ( x ) y f(\boldsymbol{x}) yf(x)&#xff0c;其中 x ( x 1 , x 2 , ⋯ , x n ) T \boldsymbol{x} (x_1, x_2, \cdots, x_n)^{\rm T} x(x1​,x2​,⋯,xn​)T是一个 n n n维列向量。标量 y y y对向量 x \boldsymbol{x} x的导数…