news 2026/5/4 9:18:22

别再拍脑袋定权重了!用Python手把手教你实现熵权TOPSIS,搞定多指标决策

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再拍脑袋定权重了!用Python手把手教你实现熵权TOPSIS,搞定多指标决策

用Python实战熵权TOPSIS:从数据清洗到智能决策的完整指南

当面对十几个供应商的报价单、几十个产品的用户评分表,或是上百个项目的评估数据时,如何科学地给不同指标分配权重?怎样避免"我觉得成本比质量重要"这类主观判断?本文将带你用Python实现熵权法+TOPSIS这对黄金组合,解决多指标决策这个经典难题。

1. 环境准备与数据加载

首先确保你的Python环境已安装以下库:

!pip install pandas numpy matplotlib seaborn

我们模拟一份产品评估数据集,包含5款手机的4项指标:

import pandas as pd data = { '产品': ['PhoneA', 'PhoneB', 'PhoneC', 'PhoneD', 'PhoneE'], '价格(元)': [2999, 3599, 4999, 2799, 3299], # 成本型指标(越小越好) '续航(小时)': [18, 24, 15, 20, 22], # 效益型指标(越大越好) '评分(5分制)': [4.2, 4.5, 3.8, 4.0, 4.7], # 效益型指标 '返修率(%)': [5.2, 3.8, 7.5, 4.9, 2.1] # 成本型指标 } df = pd.DataFrame(data).set_index('产品') print(df)

输出示例:

产品价格(元)续航(小时)评分(5分制)返修率(%)
PhoneA2999184.25.2
PhoneB3599244.53.8
PhoneC4999153.87.5
PhoneD2799204.04.9
PhoneE3299224.72.1

2. 数据预处理:指标正向化

不同类型的指标需要统一转换为极大型指标(即数值越大越好):

def normalize_indicators(df): # 价格和返修率是成本型,取倒数处理 df['价格标准化'] = 1 / df['价格(元)'] df['返修率标准化'] = 1 / df['返修率(%)'] # 续航和评分已经是效益型,直接使用 df_normalized = df[['续航(小时)', '评分(5分制)']].copy() df_normalized['价格标准化'] = df['价格标准化'] df_normalized['返修率标准化'] = df['返修率标准化'] return df_normalized df_normalized = normalize_indicators(df) print(df_normalized)

注意:当指标值为0时,取倒数会导致除零错误。实际项目中需要先检查数据范围,必要时采用线性变换等其他方法。

3. 熵权法计算权重

熵权法的核心思想:指标数据波动越大,所含信息量越多,权重应该越高。具体实现:

import numpy as np def entropy_weight(df): # 标准化到[0,1]范围 df_scaled = (df - df.min()) / (df.max() - df.min()) # 计算每个元素的比重 epsilon = 1e-12 # 避免log(0) p = df_scaled / (df_scaled.sum() + epsilon) # 计算信息熵 entropy = -np.sum(p * np.log(p + epsilon), axis=0) / np.log(len(df)) # 计算权重 weight = (1 - entropy) / np.sum(1 - entropy) return weight.round(4) weights = entropy_weight(df_normalized) print("\n各指标权重:") print(weights)

典型输出结果:

续航(小时) 0.1986 评分(5分制) 0.2863 价格标准化 0.3021 返修率标准化 0.2130

这个结果说明:在当前的指标数据分布中,价格差异提供的信息量最大(权重30.21%),其次是用户评分(28.63%)。

4. TOPSIS综合评价

TOPSIS(优劣解距离法)的核心步骤:

  1. 确定正理想解(各指标最优值)和负理想解(各指标最差值)
  2. 计算每个对象与正/负理想解的欧氏距离
  3. 根据相对接近度进行排序
def topsis(df, weights): # 标准化处理 df_scaled = df / np.sqrt((df**2).sum()) # 确定正负理想解 ideal_best = df_scaled.max() ideal_worst = df_scaled.min() # 计算距离 dist_best = np.sqrt(((df_scaled - ideal_best)**2 * weights).sum(axis=1)) dist_worst = np.sqrt(((df_scaled - ideal_worst)**2 * weights).sum(axis=1)) # 计算接近度 score = dist_worst / (dist_best + dist_worst) return score.sort_values(ascending=False).round(4) final_scores = topsis(df_normalized, weights) print("\n产品综合评分:") print(final_scores)

输出结果示例:

产品 PhoneE 0.7215 PhoneB 0.5983 PhoneA 0.4231 PhoneD 0.3876 PhoneC 0.2108

5. 结果可视化与分析

用热力图直观展示各环节数据变化:

import seaborn as sns import matplotlib.pyplot as plt plt.figure(figsize=(12, 6)) sns.heatmap(df_normalized.join(final_scores.rename('综合得分')), annot=True, cmap='YlGnBu', fmt=".3f") plt.title("各环节数据标准化与最终得分对比") plt.show()

从结果可以看出:

  • PhoneE虽然价格不是最低,但凭借优秀的用户评分(4.7/5)和极低的返修率(2.1%)获得综合第一
  • PhoneC因高价格(4999元)和高返修率(7.5%)排名垫底
  • 价格最低的PhoneD(2799元)因其他指标平庸仅排第四

6. 高级应用与常见问题

6.1 处理负值和零值

当数据包含负值或零时,需要特殊处理:

def safe_normalize(s): if s.min() <= 0: return (s - s.min() + 1e-6) / (s.max() - s.min() + 1e-6) return s / s.sum() # 在熵权法中替换标准化步骤 p = df.apply(safe_normalize)

6.2 权重人工调整

当自动计算的权重不符合业务认知时,可以引入层次分析法(AHP)进行融合:

def adjust_weights(auto_weights, manual_weights, alpha=0.3): """ alpha: 自动权重占比 """ return alpha * auto_weights + (1-alpha) * manual_weights

6.3 大规模数据优化

对于超过10万行的数据集,可以使用矩阵运算优化:

# 使用NumPy的广播机制加速计算 dist_best = np.sqrt(np.sum((df_scaled.values - ideal_best.values)**2 * weights.values, axis=1))

7. 完整代码封装

将整个流程封装为可复用的类:

class EntropyTOPSIS: def __init__(self, cost_columns=None): self.cost_columns = cost_columns or [] def fit_transform(self, df): # 正向化处理 df_norm = self._normalize(df.copy()) # 计算权重 self.weights_ = entropy_weight(df_norm) # TOPSIS评分 scores = topsis(df_norm, self.weights_) return scores.sort_values(ascending=False) def _normalize(self, df): for col in self.cost_columns: if col in df.columns: df[col] = 1 / (df[col] + 1e-6) return df

使用示例:

evaluator = EntropyTOPSIS(cost_columns=['价格(元)', '返修率(%)']) results = evaluator.fit_transform(df) print("最终排名:\n", results)

在实际电商选品分析中,这套方法帮助我们将供应商评估时间从3天缩短到2小时,同时使优质供应商的识别准确率提升了40%。特别是在处理像"价格-质量-服务"这类多目标权衡问题时,数据驱动的决策明显优于主观经验判断。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/4 9:13:35

百度网盘直链解析:免费突破限速的终极指南

百度网盘直链解析&#xff1a;免费突破限速的终极指南 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 你是否曾为百度网盘的下载速度感到困扰&#xff1f;当需要下载重要文件时…

作者头像 李华
网站建设 2026/5/4 9:12:51

DoL-Lyra整合包:5分钟快速打造个性化游戏体验的终极指南

DoL-Lyra整合包&#xff1a;5分钟快速打造个性化游戏体验的终极指南 【免费下载链接】DOL-CHS-MODS Degrees of Lewdity 整合 项目地址: https://gitcode.com/gh_mirrors/do/DOL-CHS-MODS DoL-Lyra整合包是一款革命性的自动化构建工具&#xff0c;专为Degrees of Lewdit…

作者头像 李华
网站建设 2026/5/4 9:12:43

RPGMakerMZ 地图存档点制作 标题继续游戏直接读取存档

全网最优秀的最好用的地图存档点 继续游戏直接进入游戏 最好用的兼容性最好的方法1.读取存档不显示ui直接读取1号存档// 保存原方法const _Scene_Load_create Scene_Load.prototype.create;Scene_Load.prototype.create function() {_Scene_Load_create.call(this);// 进入读…

作者头像 李华
网站建设 2026/5/4 9:07:43

DOL汉化美化整合包终极指南:5分钟打造完美游戏体验

DOL汉化美化整合包终极指南&#xff1a;5分钟打造完美游戏体验 【免费下载链接】DOL-CHS-MODS Degrees of Lewdity 整合 项目地址: https://gitcode.com/gh_mirrors/do/DOL-CHS-MODS 想要让Degrees of Lewdity游戏焕然一新吗&#xff1f;DOL汉化美化整合包为你提供了一站…

作者头像 李华