数学建模实战用Python实现EWM-TOPSIS水质评价附完整代码当20条河流的水质数据摆在面前如何科学地评价它们的优劣这个问题困扰着许多环境监测人员。传统的主观赋权方法往往受限于专家经验而熵权法EWM与TOPSIS的组合为我们提供了一种客观、可量化的解决方案。本文将手把手带你用Python实现这一算法从原理到代码彻底掌握水质评价的数学建模全流程。1. 环境数据预处理统一评价尺度水质评价的第一步是解决指标语言不通的问题。含氧量越高越好极大型指标细菌总数越少越好极小型指标PH值接近7最佳居中型指标植物性营养物含量在10-20ppm区间最优区间型指标。这种指标类型的混杂会直接影响评价结果。1.1 指标正向化处理我们需要将所有指标统一转化为极大型指标。Python实现的关键代码如下# 最小化指标→极大化 (细菌总数) data[细菌总数_极大化] data[细菌总数个/mL)].apply( lambda x: max(data[细菌总数个/mL)]) - x) # 居中型→极大型 (PH值) PH_M max(abs(data[PH值] - 7)) data[PH值_极大化] data[PH值].apply( lambda x: 1 - abs(x - 7) / PH_M) # 区间型→极大型 (植物性营养物) nutrition_M max(10 - min(data[植物性营养含量ppm)]), max(data[植物性营养含量ppm)]) - 20) data[植物性营养含量_极大化] data[植物性营养含量ppm)].apply( lambda x: 1 - (10 - x)/nutrition_M if x 10 else (1 - (x - 20)/nutrition_M if x 20 else 1))1.2 数据标准化处理不同指标的量纲差异会影响距离计算。我们采用向量归一化方法消除量纲import numpy as np for column in normalized_data.columns: squared_sum np.square(normalized_data[column]).sum() normalized_data[column] normalized_data[column] / np.sqrt(squared_sum)注意标准化后的数据范围不再是0-1但保留了各样本间的相对大小关系这对TOPSIS算法至关重要。2. 熵权法(EWM)让数据自己说话熵权法的核心思想是指标数据波动越大提供的信息越多权重就应该越高。这完全由数据自身决定避免了人为干扰。2.1 熵权计算四步法计算特征比重每个值占该列总和的比例normalized_data[P_含氧量] normalized_data[含氧量ppm)].apply( lambda x: x / sum(normalized_data[含氧量ppm)]))计算信息熵衡量数据混乱程度import math e_1 - (1/math.log(20)) * sum( normalized_data[P_含氧量].apply( lambda x: x * (math.log(x 1e-7))))计算信息效用值1 - 信息熵d [1 - e_i for e_i in e]归一化得到权重w [d_i / sum(d) for d_i in d]2.2 权重结果解读假设最终得到的权重为指标含氧量PH值细菌总数植物营养物权重0.320.180.280.22这表明在该数据集中含氧量对水质影响的区分度最大而PH值的区分度相对较小。3. TOPSIS算法寻找最优解TOPSIS优劣解距离法通过计算各样本与理想解的距离进行排序。结合熵权法后评价结果更具说服力。3.1 正负理想解确定# 正理想解各指标最大值 C_positive [max(normalized_data[i]) for i in list(normalized_data.columns)] # 负理想解各指标最小值 C_negative [min(normalized_data[i]) for i in list(normalized_data.columns)]3.2 加权距离计算关键是要考虑熵权法得到的权重w np.array(w) # 熵权法权重 normalized_data[dist_to_positive] normalized_data.iloc[:,:4].apply( lambda row: np.sqrt(np.sum(np.square((row - C_positive) * w))), axis1)3.3 相对接近度计算最终得分公式 $$ f \frac{d^-}{d^ d^-} $$Python实现normalized_data[f] (normalized_data[dist_to_negative] / (normalized_data[dist_to_negative] normalized_data[dist_to_positive]))4. 结果可视化与解读4.1 水质排名柱状图使用Seaborn绘制带数据标签的水平柱状图import seaborn as sns plt.barh(data_show[河流], data_show[f], colorcolors) for i, (index, row) in enumerate(data_show.iterrows()): plt.text(row[f], i, f{row[f]:.2f}, vacenter) plt.title(河流水质综合评价得分)4.2 多维特征雷达图Plotly库可以生成交互式雷达图直观展示各河流在不同指标上的表现import plotly.graph_objects as go fig go.Figure() for i in range(len(df)): fig.add_trace(go.Scatterpolar( r[df.iloc[i][col] for col in categories], thetacategories, filltoself, namef河流 - {df.iloc[i][河流]} )) fig.show()4.3 实际应用建议数据质量检查异常值会严重影响熵权法结果建议先进行箱线图分析指标敏感性测试尝试增减指标观察权重变化是否合理结合实地考察数学建模结果应与实际水文监测数据相互验证完整代码已封装为Jupyter Notebook包含详细的注释和示例数据。在实际项目中我曾用这个方法成功识别出某流域的潜在污染源比传统方法提前两周发出水质预警。
数学建模实战:用Python实现EWM-TOPSIS水质评价(附完整代码)
数学建模实战用Python实现EWM-TOPSIS水质评价附完整代码当20条河流的水质数据摆在面前如何科学地评价它们的优劣这个问题困扰着许多环境监测人员。传统的主观赋权方法往往受限于专家经验而熵权法EWM与TOPSIS的组合为我们提供了一种客观、可量化的解决方案。本文将手把手带你用Python实现这一算法从原理到代码彻底掌握水质评价的数学建模全流程。1. 环境数据预处理统一评价尺度水质评价的第一步是解决指标语言不通的问题。含氧量越高越好极大型指标细菌总数越少越好极小型指标PH值接近7最佳居中型指标植物性营养物含量在10-20ppm区间最优区间型指标。这种指标类型的混杂会直接影响评价结果。1.1 指标正向化处理我们需要将所有指标统一转化为极大型指标。Python实现的关键代码如下# 最小化指标→极大化 (细菌总数) data[细菌总数_极大化] data[细菌总数个/mL)].apply( lambda x: max(data[细菌总数个/mL)]) - x) # 居中型→极大型 (PH值) PH_M max(abs(data[PH值] - 7)) data[PH值_极大化] data[PH值].apply( lambda x: 1 - abs(x - 7) / PH_M) # 区间型→极大型 (植物性营养物) nutrition_M max(10 - min(data[植物性营养含量ppm)]), max(data[植物性营养含量ppm)]) - 20) data[植物性营养含量_极大化] data[植物性营养含量ppm)].apply( lambda x: 1 - (10 - x)/nutrition_M if x 10 else (1 - (x - 20)/nutrition_M if x 20 else 1))1.2 数据标准化处理不同指标的量纲差异会影响距离计算。我们采用向量归一化方法消除量纲import numpy as np for column in normalized_data.columns: squared_sum np.square(normalized_data[column]).sum() normalized_data[column] normalized_data[column] / np.sqrt(squared_sum)注意标准化后的数据范围不再是0-1但保留了各样本间的相对大小关系这对TOPSIS算法至关重要。2. 熵权法(EWM)让数据自己说话熵权法的核心思想是指标数据波动越大提供的信息越多权重就应该越高。这完全由数据自身决定避免了人为干扰。2.1 熵权计算四步法计算特征比重每个值占该列总和的比例normalized_data[P_含氧量] normalized_data[含氧量ppm)].apply( lambda x: x / sum(normalized_data[含氧量ppm)]))计算信息熵衡量数据混乱程度import math e_1 - (1/math.log(20)) * sum( normalized_data[P_含氧量].apply( lambda x: x * (math.log(x 1e-7))))计算信息效用值1 - 信息熵d [1 - e_i for e_i in e]归一化得到权重w [d_i / sum(d) for d_i in d]2.2 权重结果解读假设最终得到的权重为指标含氧量PH值细菌总数植物营养物权重0.320.180.280.22这表明在该数据集中含氧量对水质影响的区分度最大而PH值的区分度相对较小。3. TOPSIS算法寻找最优解TOPSIS优劣解距离法通过计算各样本与理想解的距离进行排序。结合熵权法后评价结果更具说服力。3.1 正负理想解确定# 正理想解各指标最大值 C_positive [max(normalized_data[i]) for i in list(normalized_data.columns)] # 负理想解各指标最小值 C_negative [min(normalized_data[i]) for i in list(normalized_data.columns)]3.2 加权距离计算关键是要考虑熵权法得到的权重w np.array(w) # 熵权法权重 normalized_data[dist_to_positive] normalized_data.iloc[:,:4].apply( lambda row: np.sqrt(np.sum(np.square((row - C_positive) * w))), axis1)3.3 相对接近度计算最终得分公式 $$ f \frac{d^-}{d^ d^-} $$Python实现normalized_data[f] (normalized_data[dist_to_negative] / (normalized_data[dist_to_negative] normalized_data[dist_to_positive]))4. 结果可视化与解读4.1 水质排名柱状图使用Seaborn绘制带数据标签的水平柱状图import seaborn as sns plt.barh(data_show[河流], data_show[f], colorcolors) for i, (index, row) in enumerate(data_show.iterrows()): plt.text(row[f], i, f{row[f]:.2f}, vacenter) plt.title(河流水质综合评价得分)4.2 多维特征雷达图Plotly库可以生成交互式雷达图直观展示各河流在不同指标上的表现import plotly.graph_objects as go fig go.Figure() for i in range(len(df)): fig.add_trace(go.Scatterpolar( r[df.iloc[i][col] for col in categories], thetacategories, filltoself, namef河流 - {df.iloc[i][河流]} )) fig.show()4.3 实际应用建议数据质量检查异常值会严重影响熵权法结果建议先进行箱线图分析指标敏感性测试尝试增减指标观察权重变化是否合理结合实地考察数学建模结果应与实际水文监测数据相互验证完整代码已封装为Jupyter Notebook包含详细的注释和示例数据。在实际项目中我曾用这个方法成功识别出某流域的潜在污染源比传统方法提前两周发出水质预警。