HuangYixin 6 months ago
parent d807e8fbd0
commit cbc64b5998

3
.idea/.gitignore vendored

@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.11 (AirQuilitySys)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="py.test" />
</component>
</module>

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.11 (AirQuilitySys)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (AirQuilitySys)" project-jdk-type="Python SDK" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/AirQuility.iml" filepath="$PROJECT_DIR$/.idea/AirQuility.iml" />
</modules>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

@ -1,76 +1,50 @@
import matplotlib.pyplot as plt import tkinter as tk
# 创建图形和坐标轴对象指定尺寸和DPI import subprocess
fig, ax = plt.subplots(figsize=(13.33,7.5), dpi = 96) import sys
# 绘制折线
for country in top_20_countries:
data = df[df['Country Name'] == country]
line = ax.plot(data['Year'], data['GDP'], label=country)
# 添加图例
ax.legend(loc="best", fontsize=8)
# 创建网格
ax.grid(which="major", axis='x', color='#DAD8D7', alpha=0.5, zorder=1)
ax.grid(which="major", axis='y', color='#DAD8D7', alpha=0.5, zorder=1)
# 重新格式化x轴标签和刻度线标签
ax.set_xlabel('', fontsize=12, labelpad=10)
# 不需要轴标签
ax.xaxis.set_label_position("bottom")
ax.xaxis.set_major_formatter(lambda s, i : f'{s:,.0f}')
#以防万一我们需要额外的格式设置
ax.xaxis.set_major_locator(MaxNLocator(integer=True))
#以防我们需要额外的格式化
ax.xaxis.set_tick_params(pad=2, labelbottom=True, bottom=True, labelsize=12, labelrotation=0)
# 重新格式化y轴
ax.set_ylabel('GDP (Billions USD)', fontsize=12, labelpad=10)
ax.yaxis.set_label_position("left")
ax.yaxis.set_major_formatter(lambda s, i : f'{s*10**-9:,.0f}')
ax.yaxis.set_major_locator(MaxNLocator(integer=True))
#以防我们需要额外的格式化
ax.yaxis.set_tick_params(pad=2, labeltop=False, labelbottom=True, bottom=False, labelsize=12)
# 颜色和线条样式 def run_DayAir():
colors_dict = {'United States': '#014f86', 'China': '#DC0000', 'Japan': '#ff4d6d', 'Germany': '#403d39', 'India': '#6a994e'} """函数用于执行另一个Python脚本"""
try:
subprocess.run(["D:\Pycharm\Project\AirQuilitySys\.venv\Scripts\python.exe", "DayAir.py"], check=True)
except subprocess.CalledProcessError as e:
print(f"执行脚本时发生错误: {e}")
line_styles_dict = {'United States': '-', 'China': '-', 'Japan': '-', 'Germany': '-', 'India': '-'} def run_DayAirzhu():
# 绘制前5条线 """函数用于执行另一个Python脚本"""
for country in top_20_countries[:5]: try:
color = colors_dict.get(country, 'grey') subprocess.run(["D:\Pycharm\Project\AirQuilitySys\.venv\Scripts\python.exe", "DayAirzhu.py"], check=True) # 尝试运行另一个Python脚本
# 从字典中获取颜色,如果找不到,默认为灰色 except subprocess.CalledProcessError as e:
line_style = line_styles_dict.get(country, '-') print(f"执行脚本时发生错误: {e}")
# 从字典中获取线条样式,如果未找到,默认为实线
data = df[df['Country Name'] == country]
line = ax.plot(data['Year'], data['GDP'], color=color, linestyle=line_style, zorder=2, label=country)
# 添加图例
ax.legend(loc="best", fontsize=8)
# 绘制剩余部分
for country in top_20_countries[5:]:
data = df[df['Country Name'] == country]
line = ax.plot(data['Year'], data['GDP'], color='grey', linestyle=':', linewidth=0.5, zorder=2)
# 移除边框
ax.spines[['top','right','bottom']].set_visible(False)
# 加粗左侧边框
ax.spines['left'].set_linewidth(1.1)
# 在顶部添加红线和矩形
ax.plot([0.05, .9], [.98, .98], transform=fig.transFigure, clip_on=False, color='#E3120B', linewidth=.6)
ax.add_patch(plt.Rectangle((0.05,.98), 0.04, -0.02, facecolor='#E3120B', transform=fig.transFigure, clip_on=False, linewidth = 0))
# 添加标题和副标题
ax.text(x=0.05, y=.93, s="Evolution of the 20 Richest Countries GDP over the Past 50 Years", transform=fig.transFigure, ha='left', fontsize=14, weight='bold', alpha=.8)
ax.text(x=0.05, y=.90, s="Focus on the current 5 richest countries from 1973 to 2022", transform=fig.transFigure, ha='left', fontsize=12, alpha=.8)
# 设置来源文本
ax.text(x=0.05, y=0.12, s="Source: World Bank - https://databank.worldbank.org/", transform=fig.transFigure, ha='left', fontsize=10, alpha=.7)
# 调整绘图区域周围的边距
plt.subplots_adjust(left=None, bottom=0.2, right=None, top=0.85, wspace=None, hspace=None)
# 设置白色背景
fig.patch.set_facecolor('white')
# 绘制前5条线
for country in top_20_countries[:5]:
color = colors_dict.get(country, 'grey')
# 从字典中获取颜色,如果找不到,默认为黑色
line_style = line_styles_dict.get(country, '-')
# 从字典中获取线条样式,如果找不到,默认为实线
data = df[df['Country Name'] == country]
line = ax.plot(data['Year'], data['GDP'], color=color, linestyle=line_style, zorder=2, label = country)
ax.plot(data['Year'].iloc[-1], data['GDP'].iloc[-1], 'o', color=color, markersize=10, alpha=0.3)
ax.plot(data['Year'].iloc[-1], data['GDP'].iloc[-1], 'o', color=color, markersize=5)
# 在图表上添加一些文字
ax.annotate('During the 2000s,\nChina began experiencing rapid economic growth,\noutpacing all other countries.', (data['Year'].iloc[-18], 2000000000000), xytext=(data['Year'].iloc[-28]-timedelta(days=500), 18000000000000), ha='left', fontsize=9, arrowprops=dict(arrowstyle='-|>', facecolor='k', connectionstyle="arc3,rad=-0.15"))
def run_DayAirbing():
"""函数用于执行另一个Python脚本"""
try:
subprocess.run(["D:\Pycharm\Project\AirQuilitySys\.venv\Scripts\python.exe", "DayAirbing.py"], check=True) # 尝试运行另一个Python脚本
except subprocess.CalledProcessError as e:
print(f"执行脚本时发生错误: {e}")
def run_time():
"""函数用于执行另一个Python脚本"""
try:
subprocess.run(["D:\Pycharm\Project\AirQuilitySys\.venv\Scripts\python.exe", "time.py"], check=True) # 尝试运行另一个Python脚本
except subprocess.CalledProcessError as e:
print(f"执行脚本时发生错误: {e}")
# 创建主窗口
window = tk.Tk()
window.title("执行外部程序示例")
# 创建一个按钮点击时调用run_another_program函数
but = tk.Button(window, text="查看每日空气折线分布图", command=run_DayAir)
but.pack(padx=20, pady=20) # 设置按钮布局
butt = tk.Button(window, text="查看每日空气柱状图", command=run_DayAirzhu)
butt.pack(padx=20, pady=20) # 设置按钮布局
butto = tk.Button(window, text="查看每月pm2.5平均指数", command=run_DayAirbing)
butto.pack(padx=20, pady=20) # 设置按钮布局
bu = tk.Button(window, text="查看未来预测数据", command=run_time)
bu.pack(padx=20, pady=20) # 设置按钮布局
# 运行Tkinter事件循环
window.mainloop()

@ -0,0 +1,123 @@
import logging
import pymysql
import subprocess
import numpy as np
from matplotlib import pyplot as plt
from tkinter import Tk
from pyecharts import options as _opts
from pyecharts.charts import Bar
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def get_data(db_config):
"""
从数据库中获取ptime和ci数据
:param db_config: 数据库配置字典
:return: 包含ptime和ci的元组列表
"""
ptime_list = [] # 存储ptime数据的列表
ci_list = [] # 存储ci数据的列表
so_list = []
try:
with pymysql.connect(**db_config) as conn:
logging.info("数据库连接成功")
with conn.cursor() as cursor:
# 使用单个查询以提高性能
sql_ptime = "SELECT ptime FROM May"
cursor.execute(sql_ptime)
data_ptime = cursor.fetchall()
#print(data_ptime)
# 处理查询结果
#for row in data:
#for row in range(len(data)):
#if row == 0:
#continue
# print(row)
ptime_list = [row['ptime'] for row in data_ptime if 'ptime' in row]
#row_list=[val for sublist in row for val in sublist]
sql_ci="SELECT ci FROM may"
cursor.execute(sql_ci)
data_ci=cursor.fetchall()
#print(data_ci)
ci_list = [row['ci'] for row in data_ci if 'ci' in row]
sql_so = "SELECT so FROM may"
cursor.execute(sql_so)
data_so = cursor.fetchall()
so_list = [row['so'] for row in data_so if 'so' in row]
sql_no = "SELECT no FROM may"
cursor.execute(sql_no)
data_no = cursor.fetchall()
no_list = [row['no'] for row in data_no if 'no' in row]
sql_pm = "SELECT pm FROM may"
cursor.execute(sql_pm)
data_pm = cursor.fetchall()
pm_list = [row['pm'] for row in data_pm if 'pm' in row]
return ptime_list, ci_list, so_list, no_list, pm_list
except pymysql.err.OperationalError as e:
logging.error(f"数据库操作失败: {e}")
# 根据具体场景,可以选择返回空列表、抛出异常或返回特定错误码
return [], [], [], [], []
#except Exception as e:
#logging.error(f"未知错误: {e}")
# 同上,根据具体场景进行处理
#return [], []
def visualize_data(ptime_list, ci_list, so_list, no_list, pm_list):
"""
可视化数据
:param ptime_list: ptime数据列表
:param ci_list: ci数据列表
:param column_to_plot: 需要绘制的列名
"""
if not ptime_list or not ci_list or not so_list or not no_list or not pm_list:
logging.error("数据为空,无法进行可视化")
return
#y_list=[]
#for i in range(4,8):
# y_list.append(i)
plt.figure(figsize=(15,10),dpi=80)
plt.xlabel('Ptime')
plt.title('CI over time')
plt.plot(ptime_list, ci_list,label='CI')
plt.plot(ptime_list, so_list,label='SO2')
plt.plot(ptime_list, no_list, label='NO2')
plt.plot(ptime_list, pm_list, label='PM2.5')
plt.legend()
plt.show()
if __name__ == "__main__":
db_config = {
"host": '127.0.0.1',
"user": "root",
"password": 'mysql>hyx123',
"db": 'airquility',
"charset": 'utf8',
"cursorclass": pymysql.cursors.DictCursor
}
ptime_list, ci_list,so_list ,no_list, pm_list= get_data(db_config)
visualize_data(ptime_list, ci_list, so_list, no_list, pm_list)
print(pymysql.__version__)
'''
window= Tk()
window.title("每日空气质量")
window.geometry("300x200")
#Label(window, text="图表已生成为air_quality_index.html").pack()
window.mainloop()
'''

@ -0,0 +1,154 @@
import logging
import pymysql
import subprocess
import numpy as np
from matplotlib import pyplot as plt
#%matplotlib inline
from tkinter import Tk
from pyecharts import options as _opts
from pyecharts.charts import Bar
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
#db_config={'host':'127.0.0.1','user':'root','password':'mysql>hyx123','db':'airquility','charset':'utf8'}
#ptimelist=[]
#cilist=[]
#data_dict=dict(zip(ptimelist,cilist))
jan_list = []
feb_list = []
mar_list = []
apr_list = []
may_list = []
ptime_list = []
def get_data(db_config):
"""
从数据库中获取ptime和ci数据
:param db_config: 数据库配置字典
:return: 包含ptime和ci的元组列表
"""
# 存储ptime数据的列表
try:
with pymysql.connect(**db_config) as conn:
logging.info("数据库连接成功")
with conn.cursor() as cursor:
# 使用单个查询以提高性能
sql_ptime = "SELECT ptime FROM May"
cursor.execute(sql_ptime)
data_ptime = cursor.fetchall()
ptime_list = [row['ptime'] for row in data_ptime if 'ptime' in row]
sql_may = "SELECT pm FROM may"
cursor.execute(sql_may)
data_may = cursor.fetchall()
may_list = [row['pm'] for row in data_may if 'pm' in row]
sql_feb="SELECT pm FROM feb"
cursor.execute(sql_feb)
data_feb=cursor.fetchall()
#print(data_ci)
feb_list = [row['pm'] for row in data_feb if 'pm' in row]
sql_jan = "SELECT pm FROM jan"
cursor.execute(sql_jan)
data_jan = cursor.fetchall()
# print(data_ci)
jan_list = [row['pm'] for row in data_jan if 'pm' in row]
sql_mar = "SELECT pm FROM mar"
cursor.execute(sql_mar)
data_mar = cursor.fetchall()
# print(data_ci)
mar_list = [row['pm'] for row in data_mar if 'pm' in row]
sql_apr = "SELECT pm FROM apr"
cursor.execute(sql_apr)
data_apr = cursor.fetchall()
# print(data_ci)
apr_list = [row['pm'] for row in data_apr if 'pm' in row]
return ptime_list, may_list, feb_list, jan_list, mar_list, apr_list
except pymysql.err.OperationalError as e:
logging.error(f"数据库操作失败: {e}")
# 根据具体场景,可以选择返回空列表、抛出异常或返回特定错误码
return [], [], [], [], [], []
def average(str_list):
if not str_list: # 检查列表是否为空
return 0 # 或者根据需要处理比如返回None或者抛出异常
num_list = [float(item) for item in str_list] # 假设可能有浮点数
return sum(num_list) / len(num_list)
def visualize_data(ptime_list, may_list, feb_list, jan_list, mar_list, apr_list):
"""
可视化数据
:param ptime_list: ptime数据列表
:param ci_list: ci数据列表
:param column_to_plot: 需要绘制的列名
"""
if not may_list or not feb_list or not jan_list:
logging.error("数据为空,无法进行可视化")
return
#y_list=[]
#for i in range(4,8):
# y_list.append(i)
x = np.arange(26)
bar_width = 0.2
# 调用函数并打印结果
jan_value = average(jan_list)
feb_value = average(feb_list)
may_value = average(may_list)
mar_value = average(mar_list)
apr_value = average(apr_list)
# 创建图形对象
fig = plt.figure("average_pm2.5")
#plt.title('每月pm2.5平均指数')
# 创建子图
ax = fig.add_axes([0, 0, 1, 1])
# 让饼状图变成圆形
ax.axis('equal')
# 准备数据
#labels = ['jan', 'feb', 'may','mar','apr']
#num_data = [jan_value, feb_value, may_value, mar_value, apr_value]
plt.figure(figsize=(15, 10), dpi=80)
plt.bar(ptime_list, apr_value, tick_label=ptime_list, width=bar_width)
plt.bar(x + bar_width, may_value, width=bar_width)
# 饼状图之间的间隙大小
#explode = (0.02, 0.03, 0.02, 0.01, 0.01)
# 画饼
#ax.pie(num_data, labels=labels, autopct='%1.1f%%', explode=explode)
plt.show()
if __name__ == "__main__":
db_config = {
"host": '127.0.0.1',
"user": "root",
"password": 'mysql>hyx123',
"db": 'airquility',
"charset": 'utf8',
"cursorclass": pymysql.cursors.DictCursor
}
ptime_list, may_list, feb_list, jan_list, mar_list, apr_list= get_data(db_config)
visualize_data(ptime_list, may_list, feb_list, jan_list, mar_list, apr_list)
#print(pymysql.__version__)
'''
window= Tk()
window.title("每日空气质量")
window.geometry("300x200")
#Label(window, text="图表已生成为air_quality_index.html").pack()
window.mainloop()
'''

@ -0,0 +1,132 @@
import logging
import pymysql
import subprocess
import numpy as np
from matplotlib import pyplot as plt
from tkinter import Tk
from pyecharts import options as _opts
from pyecharts.charts import Bar
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
#db_config={'host':'127.0.0.1','user':'root','password':'mysql>hyx123','db':'airquility','charset':'utf8'}
#ptimelist=[]
#cilist=[]
#data_dict=dict(zip(ptimelist,cilist))
def get_data(db_config):
"""
从数据库中获取ptime和ci数据
:param db_config: 数据库配置字典
:return: 包含ptime和ci的元组列表
"""
ptime_list = [] # 存储ptime数据的列表
ci_list = [] # 存储ci数据的列表
try:
with pymysql.connect(**db_config) as conn:
logging.info("数据库连接成功")
with conn.cursor() as cursor:
# 使用单个查询以提高性能
sql_ptime = "SELECT ptime FROM May"
cursor.execute(sql_ptime)
data_ptime = cursor.fetchall()
ptime_list = [row['ptime'] for row in data_ptime if 'ptime' in row]
#row_list=[val for sublist in row for val in sublist]
sql_ci="SELECT ci FROM may"
cursor.execute(sql_ci)
data_ci=cursor.fetchall()
#print(data_ci)
ci_list = [row['ci'] for row in data_ci if 'ci' in row]
sql_so = "SELECT so FROM may"
cursor.execute(sql_so)
data_so = cursor.fetchall()
so_list = [row['so'] for row in data_so if 'so' in row]
sql_no = "SELECT no FROM may"
cursor.execute(sql_no)
data_no = cursor.fetchall()
no_list = [row['no'] for row in data_no if 'no' in row]
sql_pm = "SELECT pm FROM may"
cursor.execute(sql_pm)
data_pm = cursor.fetchall()
pm_list = [row['pm'] for row in data_pm if 'pm' in row]
return ptime_list, ci_list, so_list, no_list, pm_list
except pymysql.err.OperationalError as e:
logging.error(f"数据库操作失败: {e}")
# 根据具体场景,可以选择返回空列表、抛出异常或返回特定错误码
return [], [], [], [], []
#except Exception as e:
#logging.error(f"未知错误: {e}")
# 同上,根据具体场景进行处理
#return [], []
def visualize_data(ptime_list, ci_list, so_list, no_list, pm_list):
"""
可视化数据
:param ptime_list: ptime数据列表
:param ci_list: ci数据列表
:param column_to_plot: 需要绘制的列名
"""
if not ptime_list or not ci_list or not so_list or not no_list or not pm_list:
logging.error("数据为空,无法进行可视化")
return
#y_list=[]
#for i in range(4,8):
# y_list.append(i)
plt.figure(figsize=(15,10),dpi=80)
x = np.arange(26)
bar_width = 0.2
"""
plt.bar(ptime_list, # 柱状图柱体标签值
ci_list, # 柱体高度
align='center', # 柱体对齐方式
color='red', # 柱体颜色
tick_label=ptime_list, # 刻度标签值
hatch='/') # 填充样式,越密集填充就越密
plt.bar(ptime_list, # 柱状图柱体标签值
so_list, # 柱体高度
align='center', # 柱体对齐方式
color='blue', # 柱体颜色
tick_label=ptime_list, # 刻度标签值
hatch='/') # 填充样式,越密集填充就越密
"""
plt.xlabel('Ptime')
plt.bar(ptime_list, ci_list, tick_label=ptime_list, width=bar_width)
plt.bar(x + bar_width, so_list, width=bar_width)
#plt.bar(x + bar_width, no_list, width=bar_width)
#plt.bar(x + bar_width, pm_list, width=bar_width)
plt.title('CI over time')
plt.show()
if __name__ == "__main__":
db_config = {
"host": '127.0.0.1',
"user": "root",
"password": 'mysql>hyx123',
"db": 'airquility',
"charset": 'utf8',
"cursorclass": pymysql.cursors.DictCursor
}
ptime_list, ci_list, so_list, no_list, pm_list = get_data(db_config)
visualize_data(ptime_list, ci_list, so_list, no_list, pm_list)
print(pymysql.__version__)
'''
window= Tk()
window.title("每日空气质量")
window.geometry("300x200")
#Label(window, text="图表已生成为air_quality_index.html").pack()
window.mainloop()
'''

@ -0,0 +1,63 @@
import keras
import matplotlib.pyplot as plt
import pandas as pd
import tensorflow as tf
import numpy as np
from sklearn.preprocessing import MinMaxScaler
from keras.layers import Dense, LSTM, Activation, Dropout
from keras.optimizers import SGD
colum = 13
step = 50
df = pd.read_csv('文件名')
df_for_training=df[:24000]
df_for_testing=df[24000:]
# print(df_for_testing.iloc[:, 2:])
scaler = MinMaxScaler(feature_range=(-1, 1))
df_for_training_scaled = scaler.fit_transform(df_for_training.iloc[:, 2:])
print("df_for_training_scaled shape:",df_for_training_scaled.shape)
#print(df_for_training_scaled.shape)
#print(df_for_testing_scaled.shape)
#抽取特征与标签列
def createXY(dataset, n_past):
dataX = []
dataY = []
for i in range(n_past, len(dataset)):
dataX.append(dataset[i - n_past:i, 1:dataset.shape[1]])
dataY.append(dataset[i, 0])
return np.array(dataX), np.array(dataY)
#trainX,testX数据的shape为[samples, steps, features]
trainX, trainY = createXY(df_for_training_scaled, step)
testX, testY = createXY(df_for_testing_scaled, step)
#构建模型
def build_model():
model = tf.keras.models.Sequential()
#经试验如果下一层还是LSTM的话必须将return_sequences设置为True
model.add(LSTM(20, input_shape=(step, column), return_sequences=True))
model.add(LSTM(20))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(1))
model.compile(loss='mae', optimizer=SGD(lr=0.1,momentum=0.3))
return model
lstm_net = build_model()
lstm_net.fit(trainX, trainY, batch_size=8, epochs=100)
predictions = lstm_net.predict(testX)
#进行逆变换
test_Predict_copy = np.repeat(predictions,column+1,axis=-1)
test_Predict_inverse = scaler.inverse_transform(test_Predict_copy)[:,0]
#test_Predict_inverse = scaler.inverse_transform(test_Predict)
test_label = np.array(df_for_testing['omega_vsg_1'])[50:]
testY_copy = np.repeat(np.reshape(testY,(len(testY), 1)),column+1,axis=-1)
testY_inverse = scaler = scaler.inverse_transform(testY_copy)[:,0]
plt.plot(test_Predict_inverse,color='red')
plt.plot(test_label,color='green')
plt.plot(testY_inverse, color='blue')
plt.savefig('result_test.png')

@ -1,6 +1,19 @@
from tkinter import * from tkinter import *
import subprocess
import sys
from tkinter import messagebox
user_login={'aaa':'123456','bbb':'888888','ccc':'333333'} user_login={'aaa':'123456','bbb':'888888','ccc':'333333'}
count=0 count=0
def run_AirQui():
"""函数用于执行另一个Python脚本"""
try:
#subprocess.run(["python", "AirQui.py"], check=True) # 尝试运行另一个Python脚本
#sys.exit()
subprocess.run(["D:\Pycharm\Project\AirQuilitySys\.venv\Scripts\python.exe", "AirQui.py"], check=True)
sys.exit(0)
except subprocess.CalledProcessError as e:
print(f"执行脚本时发生错误: {e}")
def login(): def login():
global count global count
username=entry_username.get() username=entry_username.get()
@ -10,13 +23,15 @@ def login():
password=entry_password.get() password=entry_password.get()
if(password==user_login[username]): if(password==user_login[username]):
label_message.config(text='登录成功!') label_message.config(text='登录成功!')
run_AirQui()
else: else:
label_message.config(text='密码错误!还可以尝试{}'.format(2-count)) label_message.config(text='密码错误!还可以尝试{}'.format(2-count))
count=count+1 count=count+1
if count == 3: if count == 3:
label_message.config(text='登录失败!') label_message.config(text='登录失败!')
btn_login.config(state="disabled") button.config(state="disabled")
# 创建主窗口
window=Tk() window=Tk()
window.title("用户登录") window.title("用户登录")
window.geometry("300x200") window.geometry("300x200")
@ -33,7 +48,13 @@ label_password.pack()
entry_password=Entry(window,show='*') entry_password=Entry(window,show='*')
entry_password.pack() entry_password.pack()
# 创建一个按钮点击时调用run_another_program函数
button = Button(window, text="登录", command=login)
button.pack() # 设置按钮布局
label_message=Label(window,text="") label_message=Label(window,text="")
label_message.pack() label_message.pack()
window.mainloop() window.mainloop()
# 运行Tkinter事件循环

@ -2,6 +2,6 @@ import requests
res = requests.get('http://www.daqi110.com/content/environment/index.html') res = requests.get('http://www.daqi110.com/content/environment/index.html')
print(res) print(res)
print(type(res)) print(type(res))
>>> #>>>
<Response [200]> #<Response [200]>
<class 'requests.models.Response'> #<class 'requests.models.Response'>

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

@ -0,0 +1 @@
import matplotlib.pyplot as plt

@ -0,0 +1,382 @@
import os
import pandas as pd
import numpy as np
from sqlalchemy import create_engine, text
from sklearn.preprocessing import MinMaxScaler
import logging
from sklearn.model_selection import train_test_split
from keras.callbacks import EarlyStopping, ModelCheckpoint
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import LSTM, Dense
from tensorflow.keras.layers import Input
from keras.preprocessing.sequence import pad_sequences
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.models import Model # 导入Model类
import matplotlib.pyplot as plt
import joblib
import pymysql
import logging
from datetime import datetime
logging.basicConfig(level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
def get_db_config():
#从环境变量中获取数据库配置。
config = {
"host": os.getenv('DB_HOST', '127.0.0.1'),
"user": os.getenv('DB_USER', 'root'),
"password": os.getenv('DB_PASSWORD','mysql>hyx123'),
"db": os.getenv('DB_NAME', 'airquility'),
"charset": 'utf8',
}
# 检查环境变量是否已设置
for key, value in config.items():
if value is None:
raise ValueError(f"缺少环境变量: {key}")
return config
def create_database_engine(config):
"""
创建数据库引擎
"""
db_string = f'mysql+pymysql://{config["user"]}:{config["password"]}@{config["host"]}/{config["db"]}?charset={config["charset"]}'
try:
engine = create_engine(db_string)
print(type(engine))
except Exception as e:
print(f"创建数据库引擎失败: {e}")
# 根据需要处理异常,例如记录日志或重试
raise # 如果需要将异常继续抛出
return engine
def fetch_data(engine, query):
"""
从数据库中获取数据
参数:
engine: 数据库连接引擎对象
query: SQL查询字符串
返回:
查询结果的数据框(df)
"""
# 确保query是字符串类型
if not isinstance(query, str):
logging.error("查询字符串类型错误query应为字符串。")
raise ValueError("查询字符串类型错误query应为字符串。")
if not query.strip():
logging.error("查询字符串为空。")
raise ValueError("查询字符串为空。")
try:
df = pd.read_sql(text(query), engine)
return df
except Exception as e:
logging.error(f"执行SQL查询失败: {e}")
raise # 重新抛出异常以便上层处理
def preprocess_data(df, target_col, default_year=2024, features=None):
"""
对数据进行预处理包括日期列转换特征标准化等
"""
# 检查df是否为空
if df.empty:
logging.error("输入的DataFrame为空")
return None, None, None
# 检查'ptime'列是否存在
if 'ptime' not in df.columns:
logging.error("DataFrame中不存在'ptime'")
return None, None, None
default_year = 2024
df['ptime'] = df['ptime'].apply(lambda x: datetime.strptime(f"{default_year}/{x}", "%Y/%m/%d"))
# 或者如果使用pd.to_datetime并且'ptime'格式特殊,需要指定格式
# df['ptime'] = pd.to_datetime(df['ptime'], errors='coerce', format='%m/%d').dt.strftime('%Y-%m-%d')
print(df.head)
# 如果'ptime'已经是datetime类型则无需转换
if df['ptime'].dtype == 'datetime64[ns]':
print("ptime列已经是以日期时间格式存储。")
else:
try:
# 尝试将'ptime'列转换为datetime类型
df['ptime'] = pd.to_datetime(df['ptime'], format='%m/%d/%Y')
except ValueError:
logging.error("ptime列转换为datetime类型失败可能是因为格式不正确。")
return None, None, None
# 设置'ptime'为索引
#df.set_index('ptime', inplace=True)
# 确定features列表
if target_col in df.columns:
features = df.columns.drop(target_col)
print("features:", features)
else:
logging.warning(f"目标列 '{target_col}' 在DataFrame中未找到将不进行列删除操作。")
features = df.columns
# 检查features是否被正确设置
if features is None:
logging.error("未找到任何特征列。")
return None, None, None
print("@@@@")
print(target_col)
print("@@@@")
try:
df.set_index('ptime', inplace=True)
except KeyError:
print("'ptime' 不存在,无法设置为索引。")
# 在这里处理缺少'ptime'的情况,比如跳过相关操作或使用其他列
# 使用MinMaxScaler进行特征缩放
scaler = MinMaxScaler()
scaled_features = scaler.fit_transform(df[features])
scaled_target = scaler.fit_transform(df.index.values.reshape(-1, 1))
print("~~~")
return scaled_features, scaled_target, scaler
def split_dataset_into_train_test(features, target, test_size=0.2):
"""
切分数据集为训练集和测试集
"""
# 检查features和target的类型以及长度是否相等
if not isinstance(features, np.ndarray) or not isinstance(target, np.ndarray):
raise TypeError("features and target must be numpy arrays")
if len(features) != len(target):
raise ValueError("features and target must have the same length")
# 检查test_size是否在合理的范围内
if not 0 < test_size < 1:
raise ValueError("test_size must be between 0 and 1")
# 计算训练集大小
train_size = int(len(features) * (1 - test_size))
# 使用numpy的切片操作这不会创建新的数据副本提高性能
train_features, test_features = features[:train_size], features[train_size:]
train_target, test_target = target[:train_size], target[train_size:]
print("123456")
print(features)
print(target)
print(train_features)
print(train_target)
print(test_features)
print(test_target)
return train_features, test_features, train_target, test_target
def validate_data_shapes(train_features, test_features, n_steps):
"""
验证训练和测试数据形状是否符合预期
"""
if train_features.shape[1] != n_steps or test_features.shape[1] != n_steps:
raise ValueError(f"训练和测试特征的第二维度(时间步长)应为{n_steps}")
print("7890")
def build_model(n_steps, lstm_units, dense_units, input_shape):
inputs = Input(shape=input_shape) # 添加Input对象
x = LSTM(lstm_units)(inputs) # 直接将Input对象传递给LSTM层
outputs = Dense(dense_units)(x)
model = tf.keras.Model(inputs=inputs, outputs=outputs)
model.compile(optimizer='adam', loss='mse')
print("!!!")
return model
def validate_params(epochs, batch_size):
"""
确保 epochs batch_size 是合法的参数
"""
if not isinstance(epochs, int) or epochs <= 0:
raise ValueError("epochs 应该是一个正整数")
if not isinstance(batch_size, int) or batch_size <= 0:
raise ValueError("batch_size 应该是一个正整数")
if epochs <= 0 or batch_size <= 0:
raise ValueError("epochs和batch_size必须大于0")
print("%%%")
def ensure_directory_safety(path:str):
"""
确保路径安全且存在
"""
if not os.path.isabs(path):
raise ValueError("路径应该是绝对路径")
directory = os.path.dirname(path)
print(directory)
try:
# 检查目录是否需要创建
if not os.path.exists(directory):
# 添加日志记录
logger.info(f"目录 {directory} 不存在,开始创建。")
# 使用 exist_ok=True 避免在目录已存在时抛出异常
os.makedirs(directory, exist_ok=True)
logger.info(f"目录 {directory} 创建成功。")
except PermissionError:
# 捕获权限异常,给出清晰的错误提示
logger.error(f"没有权限在 {directory} 创建目录。")
raise
except Exception as e:
# 捕获其他异常,记录并抛出
logger.error(f"创建目录 {directory} 时发生未知错误:{e}")
raise
print("===")
def train_model(model: Model, train_features, train_target, test_features, test_target, epochs: int, batch_size: int,
patience: int, save_best_only: bool = True, monitor: str = 'val_loss', mode: str = 'min',
model_path: str = "best_model.h5") -> dict:
"""
训练模型并根据早停策略和性能指标保存最佳模型
:param model: Keras模型实例
:param train_features: 训练特征
:param train_target: 训练目标
:param test_features: 测试特征
:param test_target: 测试目标
:param epochs: 训练轮数
:param batch_size: 批量大小
:param patience: 早停策略的耐心值
:param save_best_only: 是否只保存最佳模型
:param monitor: 监控的指标
:param mode: 监控指标的模式min/max
:param model_path: 模型保存路径
:return: 训练历史记录
"""
logging.basicConfig(level=logging.INFO)
model_path = "/path/to/your/model.h5"
validate_params(epochs, batch_size)
ensure_directory_safety(model_path)
# 使用ModelCheckpoint保存最佳模型
filepath = model_path
checkpoint = ModelCheckpoint(filepath, monitor=monitor, verbose=1, save_best_only=save_best_only, mode=mode)
# 定义早停策略
early_stopping = EarlyStopping(monitor=monitor, patience=patience, verbose=1)
try:
history = model.fit(train_features, train_target, epochs=epochs, batch_size=batch_size,
validation_data=(test_features, test_target), verbose=1,
callbacks=[early_stopping, checkpoint])
logging.info("###")
return history
except ValueError as ve:
logging.error(f"参数错误: {ve}")
raise
except OSError as oe:
logging.error(f"文件操作错误: {oe}")
raise
except Exception as e:
logging.error(f"模型训练过程中发生异常: {e}")
raise
def build_and_train_model(n_steps, features, target, train_features, train_target, test_features, test_target,lstm_units=50, dense_units=1, optimizer='adam', loss='mse', epochs=100, batch_size=32,patience=10, model_save_path='model.h5'):
"""
构建LSTM模型并进行训练增加了参数可配置性早停策略和模型保存
"""
# 输入数据验证
if not (isinstance(train_features, np.ndarray) and isinstance(train_target, np.ndarray) and isinstance(test_features, np.ndarray) and isinstance(test_target, np.ndarray)):
raise ValueError("输入数据train_features, train_target, test_features, test_target必须是numpy数组")
checkpoint = ModelCheckpoint(filepath="/path/to/your/model.keras", # 注意这里的路径保持为.h5
monitor='val_loss', # 或您希望监控的指标
verbose=1,
save_best_only=True,
mode='min')
# 数据形状验证
validate_data_shapes(train_features, test_features, n_steps)
model = build_model(n_steps, lstm_units, dense_units, input_shape)
# 早停策略
early_stopping = EarlyStopping(monitor='val_loss', patience=patience, verbose=1)
history = model.fit(train_features, train_target,
validation_data=(test_features, test_target),
epochs=epochs,
batch_size=batch_size,
callbacks=[checkpoint],
# 其他参数...
) # 模型保存
# 增加了路径验证来防止潜在的安全问题,这里简化处理,实际应用中可能需要更复杂的逻辑
if not model_save_path.endswith('.h5'):
model_save_path += '.h5'
model.save(model_save_path)
return model, history
def evaluate_model(model, scaler, test_target, predictions):
"""
评估模型性能并反向转换预测结果
"""
predictions = scaler.inverse_transform(predictions)
test_target_inv = scaler.inverse_transform(test_target.reshape(-1, 1))
mse = mean_squared_error(test_target_inv, predictions)
print(f'Mean Squared Error: {mse}')
return mse
if __name__ == "__main__":
engine = create_database_engine(get_db_config())
query = "SELECT ptime, ci FROM may"
df = fetch_data(engine, query)
target_col = 'ptime'
features, target, scaler = preprocess_data(df, target_col)
train_features, test_features, train_target, test_target = split_dataset_into_train_test(features, target, test_size=0.2)
n_steps = 5
# 假设train_features和test_features是你的数据且它们是二维数组
# 首先你需要获取或设定一个maxlen这里假设我们已知或计算出它应该是5
maxlen = 5
# 对训练数据进行填充或截断
train_features_padded = pad_sequences(train_features, maxlen=maxlen, padding='post', truncating='post')
# 对测试数据进行同样的处理
test_features_padded = pad_sequences(test_features, maxlen=maxlen, padding='post', truncating='post')
input_shape = (n_steps, int(train_features.shape[1]))
model, history = build_and_train_model(n_steps=n_steps,
features=features,
target=target,
train_target=train_target,
test_target=test_target,
train_features=train_features_padded,
test_features=test_features_padded)
predictions = model.predict(test_features)
mse = evaluate_model(model, scaler, test_target, predictions)
# 可视化预测结果(可选)
#plt.plot(test_target, label='Actual')
plt.plot(predictions, label='Predicted')
plt.legend()
plt.xlabel('Ptime')
plt.ylabel('CI')
#plt.plot(ptime, ci)
plt.show()
# 保存模型
model.save('trained_model.h5')
joblib.dump(scaler, 'scaler.joblib')

Binary file not shown.

@ -0,0 +1,44 @@
import mysql.connector
from mysql.connector import Error
def insert_user():
try:
# 连接到数据库
connection = mysql.connector.connect(
host='127.0.0.1',
user='root',
password='mysql>hyx123',
database='airquility'
)
if connection.is_connected():
db_info = connection.get_server_info()
print(f"Connected to MySQL Server version {db_info}")
cursor = connection.cursor()
# 从用户接收输入
user = input("Enter user: ")
password = input("Enter password: ")
# 准备插入数据的SQL语句
sql_insert_query = """INSERT INTO users (user,password)
VALUES (%s, %s)"""
# 用户输入的数据作为元组
insert_data = (user, password)
# 执行插入操作
cursor.execute(sql_insert_query, insert_data)
connection.commit()
print("Record inserted successfully into users table.")
except Error as e:
print(f"Error while connecting to MySQL: {e}")
finally:
if (connection.is_connected()):
cursor.close()
connection.close()
print("MySQL connection is closed")
# 调用函数插入数据
insert_user()
Loading…
Cancel
Save