Python实现TOPSIS分析法(优劣解距离法)

本文介绍了一种利用Python进行水质评价的方法,通过TOPSIS法对20条河流的水质数据进行分析,包括读取Excel数据、指标转换、正向化标准化、计算得分与归一化等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


关于Python数据分析在数学建模中的更多相关应用:Python数据分析在数学建模中的应用汇总(持续更新中!)

(1)、题目

在这里插入图片描述
题目:评价下表中20条河流的水质情况。
注:含氧量越高越好(极大型指标),PH值越接近7越好(中间型指标),细菌总数越少越好(极小型指标),植物性营养物量介于10~20之间最佳,超过20或低于10均不好(范围型指标)。

(2)、读取Excel表中的数据

def read(file):
    wb = xlrd.open_workbook(filename=file)#打开文件
    sheet = wb.sheet_by_index(0)#通过索引获取表格
    rows = sheet.nrows # 获取行数
    all_content = []        #存放读取的数据
    for j in range(1, 5):       #取第1~第4列对的数据
        temp = []
        for i in range(1,rows) :
            cell = sheet.cell_value(i, j)   #获取数据 
            temp.append(cell)           
        all_content.append(temp)    #按列添加到结果集中
        temp = []
    return np.array(all_content)

(3)、将不同的指标转换为极大型指标

#极小型指标 -> 极大型指标
def dataDirection_1(datas):         
		return np.max(datas)-datas     #套公式

#中间型指标 -> 极大型指标
def dataDirection_2(datas, x_best):
    temp_datas = datas - x_best
    M = np.max(abs(temp_datas))
    answer_datas = 1 - abs(datas - x_best) / M     #套公式
    return answer_datas
    
#区间型指标 -> 极大型指标
def dataDirection_3(datas, x_min, x_max):
    M = max(x_min - np.min(datas), np.max(datas) - x_max)
    answer_list = []
    for i in datas:
        if(i < x_min):
            answer_list.append(1 - (x_min-i) /M)      #套公式
        elif( x_min <= i <= x_max):
            answer_list.append(1)
        else:
            answer_list.append(1 - (i - x_max)/M)
    return np.array(answer_list)   

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(4)、正向化矩阵标准化

def temp2(datas):
    K = np.power(np.sum(pow(datas,2),axis =1),0.5)
    for i in range(0,K.size):
        for j in range(0,datas[i].size):
            datas[i,j] = datas[i,j] / K[i]      #套用矩阵标准化的公式
    return datas 

在这里插入图片描述

(5)、计算得分并归一化

def temp3(answer2):
    list_max = np.array([np.max(answer2[0,:]),np.max(answer2[1,:]),np.max(answer2[2,:]),np.max(answer2[3,:])])  #获取每一列的最大值
    list_min = np.array([np.min(answer2[0,:]),np.min(answer2[1,:]),np.min(answer2[2,:]),np.min(answer2[3,:])])  #获取每一列的最小值
    max_list = []       #存放第i个评价对象与最大值的距离
    min_list = []       #存放第i个评价对象与最小值的距离
    answer_list=[]      #存放评价对象的未归一化得分
    for k in range(0,np.size(answer2,axis = 1)):        #遍历每一列数据
        max_sum = 0
        min_sum = 0
        for q in range(0,4):                                #有四个指标
            max_sum += np.power(answer2[q,k]-list_max[q],2)     #按每一列计算Di+
            min_sum += np.power(answer2[q,k]-list_min[q],2)     #按每一列计算Di-
        max_list.append(pow(max_sum,0.5))
        min_list.append(pow(min_sum,0.5))
        answer_list.append(min_list[k]/ (min_list[k] + max_list[k]))    #套用计算得分的公式 Si = (Di-) / ((Di+) +(Di-))
        max_sum = 0
        min_sum = 0
    answer = np.array(answer_list)      #得分归一化
    return (answer / np.sum(answer))

在这里插入图片描述

(6)、主函数

def main():
    file = 'C:\\Users\\lenovo\Desktop\\数学建模\\TOPSIS法\\第2讲.TOPSIS法(优劣解距离法)7.17\\代码和例题数据\\20条河流的水质情况数据.xlsx'
    answer1 = read(file)        #读取文件
    answer2 = []
    for i in range(0, 4):       #按照不同的列,根据不同的指标转换为极大型指标,因为只有四列
        answer = None
        if(i == 0):             #本来就是极大型指标,不用转换
            answer = answer1[0]             
        elif(i == 1):                   #中间型指标
            answer = dataDirection_2(answer1[1],7)
        elif(i==2):                     #极小型指标
            answer = dataDirection_1(answer1[2])
        else:                           #范围型指标
            answer = dataDirection_3(answer1[3],10,20)
        answer2.append(answer)
    answer2 = np.array(answer2)         #将list转换为numpy数组
    answer3 = temp2(answer2)            #数组正向化
    answer4 = temp3(answer3)            #标准化处理去钢
    data = pd.DataFrame(answer4)        #计算得分
    
    #将得分输出到excel表格中
    writer = pd.ExcelWriter('C:\\Users\\lenovo\Desktop\\数学建模\\TOPSIS法\\第2讲.TOPSIS法(优劣解距离法)7.17\\代码和例题数据\\A.xlsx')		# 写入Excel文件
    data.to_excel(writer, 'page_1', float_format='%.5f')		# ‘page_1’是写入excel的sheet名
    writer.save()
    writer.close()

(7)、完整代码部分

# -*- coding: utf-8 -*-
"""
Created on Sat Jul 27 21:36:55 2019

@author: lenovo
"""
import numpy as np
import xlrd
import pandas as pd

#从excel文件中读取数据
def read(file):
    wb = xlrd.open_workbook(filename=file)#打开文件
    sheet = wb.sheet_by_index(0)#通过索引获取表格
    rows = sheet.nrows # 获取行数
    all_content = []        #存放读取的数据
    for j in range(1, 5):       #取第1~第4列对的数据
        temp = []
        for i in range(1,rows) :
            cell = sheet.cell_value(i, j)   #获取数据 
            temp.append(cell)           
        all_content.append(temp)    #按列添加到结果集中
        temp = []
    return np.array(all_content)

#极小型指标 -> 极大型指标
def dataDirection_1(datas):         
		return np.max(datas)-datas     #套公式

#中间型指标 -> 极大型指标
def dataDirection_2(datas, x_best):
    temp_datas = datas - x_best
    M = np.max(abs(temp_datas))
    answer_datas = 1 - abs(datas - x_best) / M     #套公式
    return answer_datas
    
#区间型指标 -> 极大型指标
def dataDirection_3(datas, x_min, x_max):
    M = max(x_min - np.min(datas), np.max(datas) - x_max)
    answer_list = []
    for i in datas:
        if(i < x_min):
            answer_list.append(1 - (x_min-i) /M)      #套公式
        elif( x_min <= i <= x_max):
            answer_list.append(1)
        else:
            answer_list.append(1 - (i - x_max)/M)
    return np.array(answer_list)   
 
#正向化矩阵标准化
def temp2(datas):
    K = np.power(np.sum(pow(datas,2),axis =1),0.5)
    for i in range(0,K.size):
        for j in range(0,datas[i].size):
            datas[i,j] = datas[i,j] / K[i]      #套用矩阵标准化的公式
    return datas

#计算得分并归一化
def temp3(answer2):
    list_max = np.array([np.max(answer2[0,:]),np.max(answer2[1,:]),np.max(answer2[2,:]),np.max(answer2[3,:])])  #获取每一列的最大值
    list_min = np.array([np.min(answer2[0,:]),np.min(answer2[1,:]),np.min(answer2[2,:]),np.min(answer2[3,:])])  #获取每一列的最小值
    max_list = []       #存放第i个评价对象与最大值的距离
    min_list = []       #存放第i个评价对象与最小值的距离
    answer_list=[]      #存放评价对象的未归一化得分
    for k in range(0,np.size(answer2,axis = 1)):        #遍历每一列数据
        max_sum = 0
        min_sum = 0
        for q in range(0,4):                                #有四个指标
            max_sum += np.power(answer2[q,k]-list_max[q],2)     #按每一列计算Di+
            min_sum += np.power(answer2[q,k]-list_min[q],2)     #按每一列计算Di-
        max_list.append(pow(max_sum,0.5))
        min_list.append(pow(min_sum,0.5))
        answer_list.append(min_list[k]/ (min_list[k] + max_list[k]))    #套用计算得分的公式 Si = (Di-) / ((Di+) +(Di-))
        max_sum = 0
        min_sum = 0
    answer = np.array(answer_list)      #得分归一化
    return (answer / np.sum(answer))


def main():
    file = 'C:\\Users\\lenovo\Desktop\\数学建模\\TOPSIS法\\第2讲.TOPSIS法(优劣解距离法)7.17\\代码和例题数据\\20条河流的水质情况数据.xlsx'
    answer1 = read(file)        #读取文件
    answer2 = []
    for i in range(0, 4):       #按照不同的列,根据不同的指标转换为极大型指标,因为只有四列
        answer = None
        if(i == 0):             #本来就是极大型指标,不用转换
            answer = answer1[0]             
        elif(i == 1):                   #中间型指标
            answer = dataDirection_2(answer1[1],7)
        elif(i==2):                     #极小型指标
            answer = dataDirection_1(answer1[2])
        else:                           #范围型指标
            answer = dataDirection_3(answer1[3],10,20)
        answer2.append(answer)
    answer2 = np.array(answer2)         #将list转换为numpy数组
    answer3 = temp2(answer2)            #数组正向化
    answer4 = temp3(answer3)            #标准化处理去钢
    data = pd.DataFrame(answer4)        #计算得分
    
    #将得分输出到excel表格中
    writer = pd.ExcelWriter('C:\\Users\\lenovo\Desktop\\数学建模\\TOPSIS法\\第2讲.TOPSIS法(优劣解距离法)7.17\\代码和例题数据\\A.xlsx')		# 写入Excel文件
    data.to_excel(writer, 'page_1', float_format='%.5f')		# ‘page_1’是写入excel的sheet名
    writer.save()
    writer.close()

main()

(8)、计算结果

在这里插入图片描述
计算出结果后可通过excel表对得分进行手动排序

### TOPSIS 方法 Python 实现代码 TOPSIS 法是一种常用的多属性决策分析方法,用于评估多个备选方案并对其进行排序。以下是基于所描述的过程实现的一个简单的 Python 版本的 TOPSIS 算法[^1]。 #### 数据准备阶段 为了简化说明,假设已经有一个包含不同选项及其对应指标的数据集,并且这些数据已经被整理成 Pandas DataFrame 的形式。 ```python import pandas as pd import numpy as np # 创建示例数据框 df data = { 'Option': ['A', 'B', 'C'], 'Cost ($)': [20, 30, 40], 'Performance (score)': [85, 90, 88], 'Reliability (%)': [95, 97, 96] } df = pd.DataFrame(data).set_index('Option') print(df) ``` #### 正向化矩阵构建 对于成本型指标(越低越好),需要将其转换为效益型指标;而对于其他类型的指标,则保持不变。 ```python def normalize_data(df): normalized_df = df.copy() # 假设 Cost 是成本型指标,其余都是效益型指标 cost_columns = ['Cost ($)'] benefit_columns = list(set(df.columns) - set(cost_columns)) for col in cost_columns: max_val = df[col].max() min_val = df[col].min() normalized_df[col] = ((max_val - df[col]) / (max_val - min_val)) * (df[col].max() - df[col].min()) + df[col].min() return normalized_df normalized_df = normalize_data(df) print("\nNormalized Data:\n", normalized_df) ``` #### 权重分配与加权规范化矩阵计算 给定各指标的重要性权重 w 后,可以得到加权后的规范化矩阵 V。 ```python weights = {'Cost ($)': 0.4, 'Performance (score)': 0.3, 'Reliability (%)': 0.3} weighted_normalized_df = normalized_df.mul(pd.Series(weights), axis=1) print("\nWeighted Normalized Matrix:\n", weighted_normalized_df) ``` #### 寻找理想解和负理想解 根据加权规范化矩阵求得 PIS 和 NIS。 ```python pis = weighted_normalized_df.max(axis=0) nis = weighted_normalized_df.min(axis=0) print(f"\nPIS: {pis}") print(f"NIS: {nis}\n") ``` #### 计算相对接近度 C* 通过公式 \(D_i^*=\sqrt{\sum_{j=1}^{m}(v_{ij}-p_j)^2}\),\(D_i^{-}=\sqrt{\sum_{j=1}^{m}(v_{ij}-n_j)^2}\),以及 \(\frac{D_i^-}{D_i^*+D_i^-}\) 来衡量每个样本相对于最优最差解决方案的距离,并据此得出综合评分 Ci*。 ```python di_star = np.sqrt(((weighted_normalized_df.values - pis)**2).sum(axis=1)) di_minus = np.sqrt(((weighted_normalized_df.values - nis)**2).sum(axis=1)) ci_star = di_minus/(di_star + di_minus) result = pd.DataFrame({'Ci*': ci_star}, index=df.index) final_result = result.sort_values(by='Ci*', ascending=False) print(final_result) ``` 此段代码实现了完整的 TOPSIS 流程,从原始数据输入到最后的结果输出都进行了详细的展示。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值