别再拍脑袋定权重了!用Python手把手教你实现熵权TOPSIS(附完整代码与数据)
用Python实战熵权TOPSIS从数据清洗到科学决策的全流程指南当我们需要对多个候选方案进行综合评价时如何避免主观赋权带来的偏差熵权TOPSIS组合模型提供了一种数据驱动的客观解决方案。这个方法论在学术研究、企业决策和工程评估中都有广泛应用但很多实践者仍停留在理论层面不知如何落地。本文将用完整的Python代码演示如何从原始数据到科学决策。1. 环境准备与数据加载工欲善其事必先利其器。我们需要配置一个稳定的分析环境import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler import matplotlib.pyplot as plt plt.style.use(ggplot) # 使用更美观的绘图样式假设我们有一个供应商评估的Excel文件包含以下指标价格万元越小越好交货周期天越小越好质量合格率%越大越好售后服务评分1-10分越大越好# 读取示例数据 data pd.read_excel(supplier_evaluation.xlsx) print(原始数据预览) print(data.head()) # 保存原始列名便于后续处理 columns data.columns.tolist()2. 数据预处理指标正向化不同类型的指标需要统一转换为极大型效益型指标def normalize_indicators(df): 指标正向化处理 df_normalized df.copy() # 极小型 - 极大型 df_normalized[价格] df[价格].max() - df[价格] df_normalized[交货周期] df[交货周期].max() - df[交货周期] return df_normalized normalized_data normalize_indicators(data) print(\n正向化后数据) print(normalized_data.head())3. 数据标准化消除量纲影响不同指标的量纲和量级差异会影响结果需要进行标准化def standardize_data(df): Z-score标准化 scaler MinMaxScaler() # 采用MinMax标准化到[0,1]区间 scaled_array scaler.fit_transform(df) return pd.DataFrame(scaled_array, columnsdf.columns) standardized_data standardize_data(normalized_data) print(\n标准化后矩阵) print(standardized_data)4. 熵权法计算指标权重通过信息熵计算各指标的客观权重def calculate_entropy_weights(df): 计算熵权 # 计算比重矩阵 p df.div(df.sum(axis0), axis1) # 计算信息熵 k 1 / np.log(len(df)) entropy -k * (p * np.log(p)).sum(axis0) # 计算权重 diversity 1 - entropy weights diversity / diversity.sum() return weights.round(4) weights calculate_entropy_weights(standardized_data) print(\n各指标权重) print(weights)5. TOPSIS综合评价结合权重计算各方案与理想解的相对接近度def topsis_method(df, weights): 带权重的TOPSIS评价 # 加权标准化矩阵 weighted_matrix df * weights.values # 确定理想解和负理想解 ideal_best weighted_matrix.max() ideal_worst weighted_matrix.min() # 计算距离 d_best np.sqrt(((weighted_matrix - ideal_best) ** 2).sum(axis1)) d_worst np.sqrt(((weighted_matrix - ideal_worst) ** 2).sum(axis1)) # 计算相对接近度 score d_worst / (d_best d_worst) return score.sort_values(ascendingFalse).round(4) final_scores topsis_method(standardized_data, weights) print(\n供应商综合评价得分) print(final_scores)6. 结果可视化与分析直观展示评价结果def visualize_results(scores, original_data): 结果可视化 fig, ax plt.subplots(figsize(10, 6)) # 绘制雷达图展示各供应商表现 categories original_data.columns.tolist() N len(categories) angles np.linspace(0, 2 * np.pi, N, endpointFalse).tolist() angles angles[:1] # 闭合图形 for idx in range(3): # 展示前三名供应商 values original_data.iloc[scores.index[idx]].tolist() values values[:1] ax.plot(angles, values, linewidth2, labelf供应商{scores.index[idx]1} (得分:{scores.iloc[idx]})) ax.fill(angles, values, alpha0.25) ax.set_xticks(angles[:-1]) ax.set_xticklabels(categories) ax.set_title(TOP3供应商各指标表现对比, pad20) ax.legend(locupper right, bbox_to_anchor(1.3, 1)) plt.tight_layout() plt.show() visualize_results(final_scores, data)7. 实战中的常见问题与解决方案在实际应用中我们经常会遇到一些典型问题指标相关性处理问题多个指标高度相关导致信息重复解决方案先进行PCA降维或删除相关性0.9的指标数据缺失处理问题部分供应商某些指标缺失解决方案采用列均值填充或使用随机森林预测缺失值权重合理性检验def check_weights_reasonableness(weights, threshold0.1): 检查是否有指标权重过低 return weights[weights threshold].index.tolist() low_weight_indicators check_weights_reasonableness(weights) print(f\n需要人工复核的指标{low_weight_indicators})敏感性分析通过微调权重观察排名变化评估模型稳定性8. 进阶应用动态权重调整对于需要随时间变化的评价场景我们可以实现动态权重def dynamic_entropy_topsis(data_series, window_size5): 滑动窗口动态评价 results [] for i in range(len(data_series) - window_size 1): window_data data_series[i:iwindow_size] weights calculate_entropy_weights(window_data) scores topsis_method(window_data, weights) results.append(scores) return pd.concat(results, axis1) # 假设我们有按时间排序的多个评价周期数据 # dynamic_scores dynamic_entropy_topsis(standardized_data)9. 与其他评价方法的对比为验证模型效果我们可以对比几种常见方法方法优点局限性适用场景熵权TOPSIS客观赋权计算简单无法处理模糊信息数据量适中的精确评价AHP能处理定性指标主观性强一致性检验复杂专家经验主导的评估灰色关联对小样本适应好分辨率有时较低数据稀缺的不确定系统DEA不需要预设权重无法直接排序效率评价10. 完整项目结构建议对于实际项目推荐以下文件结构/project_root │── /data │ ├── raw_data.xlsx # 原始数据 │ └── processed_data.csv # 处理后的数据 │── /notebooks │ ├── 1_data_exploration.ipynb │ └── 2_entropy_topsis.ipynb │── /src │ ├── preprocessing.py # 数据预处理函数 │ └── evaluation.py # 评价模型核心代码 │── requirements.txt # 依赖库 └── README.md # 项目说明在数据科学项目中这种结构既保证了代码的可复用性又便于团队协作和结果复现。实际开发时可以将核心函数封装为Python模块通过Jupyter Notebook进行交互式分析。