资讯动态

Topsis算法实战:用Python替代MATLAB完成综合评价(附完整代码)

发布时间:2026/8/15 8:24:02 来源:尧图企业网站定制
Topsis算法实战用Python替代MATLAB完成综合评价附完整代码在数据分析和科研领域综合评价方法一直是决策支持的重要工具。TOPSISTechnique for Order Preference by Similarity to Ideal Solution算法又称优劣解距离法因其直观的计算逻辑和可靠的结果表现成为多指标决策分析中的明星算法。传统上许多研究者习惯使用MATLAB实现TOPSIS但随着Python在科学计算领域的崛起越来越多的数据分析师开始寻求更灵活、更现代的解决方案。本文将带你从零开始用Python完整实现TOPSIS算法特别针对从MATLAB迁移到Python的用户详细解析两种语言在矩阵运算上的关键差异。我们不仅会提供可直接运行的完整代码还会通过真实数据集演示整个分析流程包括数据预处理、算法实现、结果可视化和性能对比帮助你无缝切换到Python工作流。1. TOPSIS算法核心原理与Python实现路径TOPSIS法的核心思想很直观在归一化的数据空间中找出理想最优解和理想最劣解然后计算每个评价对象与这两个参考点的距离最后根据相对接近度进行排序。这种距离产生美的评价方法避免了主观赋权的偏差特别适合处理多指标决策问题。Python实现TOPSIS的五个关键步骤数据准备与正向化处理不同量纲和方向的指标数据标准化消除量纲影响常见方法有向量归一化确定权重可以使用等权重或通过AHP等方法确定计算距离欧氏距离是最常用的度量方式计算接近度基于与理想解的距离比进行排序与MATLAB相比Python实现时需要注意几个关键差异点矩阵运算MATLAB默认支持矩阵运算而Python需要借助NumPy库索引方式Python从0开始索引MATLAB从1开始函数定义Python的函数参数传递更灵活但需要注意可变对象的问题可视化Python的Matplotlib与MATLAB语法相似但API设计更面向对象import numpy as np import pandas as pd def topsis(data, weightsNone, impactsNone): TOPSIS算法Python实现 参数 data: 原始数据矩阵 (numpy数组或pandas DataFrame) weights: 各指标权重 (None表示等权重) impacts: 各指标方向 (1表示正向指标-1表示负向指标) 返回 综合得分及排名 # 数据预处理与校验 if isinstance(data, pd.DataFrame): data data.values if weights is None: weights np.ones(data.shape[1]) / data.shape[1] if impacts is None: impacts np.ones(data.shape[1]) # 数据标准化 norm_data data / np.linalg.norm(data, axis0) # 加权标准化矩阵 weighted_norm norm_data * weights # 理想解与负理想解 ideal_best np.max(weighted_norm * impacts, axis0) ideal_worst np.min(weighted_norm * impacts, axis0) # 距离计算 dist_best np.linalg.norm(weighted_norm - ideal_best, axis1) dist_worst np.linalg.norm(weighted_norm - ideal_worst, axis1) # 接近度计算 score dist_worst / (dist_best dist_worst) return score / np.sum(score) # 归一化得分2. 从MATLAB到Python的关键迁移策略对于习惯MATLAB的用户迁移到Python时需要特别注意以下几个技术点的差异处理2.1 矩阵运算的等效实现MATLAB的矩阵运算是其核心优势而Python需要通过NumPy实现类似功能。下表展示了常见操作的对比操作类型MATLAB实现Python等效实现矩阵创建A [1 2; 3 4]A np.array([[1,2],[3,4]])元素运算A .* BA * B矩阵乘法A * Bnp.dot(A, B)或A B矩阵转置AA.T矩阵求逆inv(A)np.linalg.inv(A)特征分解[V,D] eig(A)D, V np.linalg.eig(A)提示Python中使用运算符进行矩阵乘法比np.dot()更直观是Python 3.5的新特性2.2 数据预处理的正向化处理TOPSIS算法要求所有指标同趋势化通常需要将负向指标转换为正向指标。常见的指标类型和处理方法包括极大型指标值越大越好无需处理极小型指标值越小越好可用倒数法或差值法转换中间型指标越接近某个中间值越好区间型指标落在某个区间内最好def normalize_indicators(data, indicator_types): 指标正向化处理 参数 data: 原始数据 (n_samples, n_features) indicator_types: 各指标类型列表 max - 极大型 min - 极小型 mid - 中间型 (需提供最佳值) range - 区间型 (需提供最佳区间) 返回 正向化后的数据 normalized data.copy() for i, (col, typ) in enumerate(zip(data.T, indicator_types)): if typ[0] max: continue # 已经是正向指标 elif typ[0] min: normalized[:, i] np.max(col) - col # 差值法 elif typ[0] mid: best_val typ[1] M np.max(np.abs(col - best_val)) normalized[:, i] 1 - np.abs(col - best_val) / M elif typ[0] range: low, high typ[1], typ[2] M max(low - np.min(col), np.max(col) - high) normalized[:, i] np.where( col low, 1 - (low - col)/M, np.where(col high, 1 - (col - high)/M, 1) ) return normalized2.3 性能优化技巧Python在数值计算性能上可以通过以下方式优化向量化操作避免Python循环使用NumPy的向量化运算内存预分配提前初始化数组避免动态扩展使用高效库对于大型矩阵考虑使用scipy.sparse并行计算对独立计算使用multiprocessing或joblib# 性能对比Python与MATLAB的TOPSIS实现 import timeit # Python实现 def py_topsis(data): # ... 上述TOPSIS实现代码 ... return scores # MATLAB引擎调用需安装MATLAB Engine API for Python import matlab.engine eng matlab.engine.start_matlab() def ml_topsis(data): # 将数据转换为MATLAB格式 ml_data matlab.double(data.tolist()) scores eng.topsis(ml_data) return np.array(scores).flatten() # 性能测试 data np.random.rand(1000, 10) py_time timeit.timeit(lambda: py_topsis(data), number100) ml_time timeit.timeit(lambda: ml_topsis(data), number100) print(fPython平均耗时: {py_time/100:.4f}s) print(fMATLAB平均耗时: {ml_time/100:.4f}s)3. 完整案例城市空气质量评价让我们通过一个实际案例演示完整的Python实现流程。假设我们需要评价10个城市的空气质量考虑以下指标PM2.5浓度μg/m³负向指标优良天数比例%正向指标SO2排放量吨负向指标绿化覆盖率%正向指标3.1 数据准备与预处理# 模拟数据 cities [北京, 上海, 广州, 深圳, 成都, 重庆, 杭州, 武汉, 西安, 天津] data np.array([ [58, 72, 12000, 38], # 北京 [45, 78, 9000, 35], # 上海 [42, 85, 8000, 40], # 广州 [38, 88, 7500, 42], # 深圳 [65, 68, 11000, 36], # 成都 [70, 65, 15000, 32], # 重庆 [48, 80, 7000, 45], # 杭州 [62, 70, 13000, 34], # 武汉 [75, 60, 16000, 30], # 西安 [55, 75, 10000, 37] # 天津 ]) # 指标类型min表示负向指标max表示正向指标 indicator_types [ (min,), # PM2.5 (max,), # 优良天数 (min,), # SO2排放 (max,) # 绿化覆盖率 ] # 指标权重专家打分法确定 weights np.array([0.3, 0.25, 0.25, 0.2]) # 数据正向化 normalized_data normalize_indicators(data, indicator_types)3.2 TOPSIS计算与结果分析# 计算TOPSIS得分 scores topsis(normalized_data, weights) # 结果排序 ranking pd.DataFrame({ 城市: cities, 得分: scores, 排名: np.argsort(-scores) 1 }).sort_values(排名) print(ranking) # 可视化结果 import matplotlib.pyplot as plt plt.figure(figsize(10, 6)) bars plt.barh(ranking[城市], ranking[得分], colorskyblue) plt.xlabel(综合得分) plt.title(城市空气质量TOPSIS评价结果) plt.gca().invert_yaxis() # 得分从高到低排列 # 添加数据标签 for bar in bars: width bar.get_width() plt.text(width 0.01, bar.get_y() bar.get_height()/2, f{width:.3f}, haleft, vacenter) plt.tight_layout() plt.show()3.3 结果解读与敏感性分析从评价结果可以看出深圳、广州和杭州位列前三这与这些城市在环保方面的投入和地理位置优势相符。而西安、重庆等内陆城市由于地理条件和工业结构原因排名相对靠后。敏感性分析是TOPSIS应用中的重要环节用于验证权重分配的合理性def sensitivity_analysis(data, base_weights, variations0.1, steps5): 权重敏感性分析 参数 data: 标准化后的数据 base_weights: 基础权重 variations: 权重变化范围 (±variations) steps: 每个方向的变化步数 返回 各指标权重变化对排名的影响 results [] n_indicators data.shape[1] for i in range(n_indicators): weight_changes np.linspace(-variations, variations, 2*steps1) for change in weight_changes: if change 0: continue # 跳过基础权重 temp_weights base_weights.copy() temp_weights[i] change # 调整其他权重保持总和为1 temp_weights / temp_weights.sum() scores topsis(data, temp_weights) top_city cities[np.argmax(scores)] results.append({ 指标: i, 权重变化: change, 第一名: top_city }) return pd.DataFrame(results) # 执行敏感性分析 sens_results sensitivity_analysis(normalized_data, weights) pivot_results sens_results.pivot_table( index权重变化, columns指标, values第一名, aggfunclambda x: x.iloc[0] ) print(权重敏感性分析结果) print(pivot_results)4. 工程实践构建可复用的TOPSIS评估系统在实际项目中我们往往需要将TOPSIS算法封装成可复用的评估系统。以下是几个关键设计考虑4.1 面向对象的TOPSIS实现class TopsisEvaluator: def __init__(self, data, indicator_types, weightsNone): 初始化TOPSIS评估器 参数 data: 原始数据 (n_samples, n_features) indicator_types: 各指标类型列表 weights: 各指标权重 (None表示等权重) self.raw_data np.array(data) self.indicator_types indicator_types self.weights (np.ones(self.raw_data.shape[1]) / self.raw_data.shape[1] if weights is None else np.array(weights)) self.normalized_data None self.scores None def normalize_data(self): 数据正向化处理 self.normalized_data normalize_indicators(self.raw_data, self.indicator_types) def calculate_scores(self): 计算TOPSIS得分 if self.normalized_data is None: self.normalize_data() # 加权标准化矩阵 weighted_norm self.normalized_data * self.weights # 理想解 ideal_best np.max(weighted_norm, axis0) ideal_worst np.min(weighted_norm, axis0) # 距离计算 dist_best np.linalg.norm(weighted_norm - ideal_best, axis1) dist_worst np.linalg.norm(weighted_norm - ideal_worst, axis1) # 接近度 self.scores dist_worst / (dist_best dist_worst) return self.scores / np.sum(self.scores) # 归一化 def evaluate(self, namesNone): 完整评估流程 scores self.calculate_scores() results pd.DataFrame({ 名称: names if names is not None else np.arange(len(scores)), 得分: scores, 排名: np.argsort(-scores) 1 }) return results.sort_values(排名) def visualize(self, namesNone, titleTOPSIS评价结果): 结果可视化 results self.evaluate(names) plt.figure(figsize(10, 6)) bars plt.barh(results[名称], results[得分], colorlightgreen) plt.xlabel(综合得分) plt.title(title) plt.gca().invert_yaxis() for bar in bars: width bar.get_width() plt.text(width 0.01, bar.get_y() bar.get_height()/2, f{width:.3f}, haleft, vacenter) plt.tight_layout() return plt # 使用示例 evaluator TopsisEvaluator(data, indicator_types, weights) results evaluator.evaluate(cities) evaluator.visualize(cities, 城市空气质量评价).show()4.2 异常处理与日志记录在实际应用中健壮的错误处理机制必不可少import logging class TopsisError(Exception): 自定义TOPSIS异常 pass def safe_topsis(data, weightsNone, impactsNone): 带异常处理的TOPSIS实现 try: # 输入验证 if not isinstance(data, (np.ndarray, pd.DataFrame)): raise TopsisError(输入数据必须是NumPy数组或Pandas DataFrame) if isinstance(data, pd.DataFrame): data data.values if weights is not None and len(weights) ! data.shape[1]: raise TopsisError(权重数量与指标数量不匹配) if impacts is not None and len(impacts) ! data.shape[1]: raise TopsisError(影响方向数量与指标数量不匹配) # 执行计算 return topsis(data, weights, impacts) except Exception as e: logging.error(fTOPSIS计算失败: {str(e)}) raise TopsisError(fTOPSIS计算过程中发生错误: {str(e)})4.3 性能优化与大规模数据处理当处理大规模数据时可以考虑以下优化策略分块处理对于超大规模数据将数据分块处理内存映射使用np.memmap处理超出内存的数据并行计算利用多核CPU加速计算from multiprocessing import Pool def parallel_topsis(data_chunks, weights, n_processes4): 并行TOPSIS计算 参数 data_chunks: 分块后的数据列表 weights: 各指标权重 n_processes: 进程数 返回 合并后的得分 def worker(chunk): return topsis(chunk, weights) with Pool(n_processes) as pool: results pool.map(worker, data_chunks) # 合并结果 (假设分块是按行分割) return np.concatenate(results) # 使用示例 large_data np.random.rand(100000, 20) # 10万样本20指标 chunks np.array_split(large_data, 4) # 分成4块 scores parallel_topsis(chunks, np.ones(20)/20)在真实项目中TOPSIS算法往往需要与其他技术结合使用。比如结合AHP层次分析法确定权重或使用熵权法进行客观赋权。Python丰富的科学计算生态让这些组合应用变得简单高效。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价