目录
介绍:
模板:
案例:
极小型指标转化为极大型(正向化):
中间型指标转为极大型(正向化):
区间型指标转为极大型(正向化):
标准化处理:
公式:
Topsis(优劣解距离法):
公式:
完整代码:
结果:
介绍:
在数学建模中,Topsis方法是一种多准则决策分析方法,用于评估和排序备选方案。它代表了“最佳方案相似性排序技术”。
在Topsis方法中,每个备选方案根据一组准则进行评估,并分配权重,以反映它们的相对重要性。然后,该方法根据每个备选方案与理想解和负理想解之间的差异计算两个度量值:到理想解的距离和到负理想解的距离。
理想解代表了每个准则的最佳可能值,而负理想解则代表了最差可能值。这些距离度量值使用一个公式计算,考虑了备选方案与这两个参考点之间差异的加权总和。
一旦计算出距离,Topsis根据备选方案与理想解的接近度对其进行排序。与理想解最接近且与负理想解最远的备选方案被视为最佳选择。
Topsis方法常用于需要考虑多个准则的决策情景中,例如选择供应商、评估项目或选择最佳行动方案。它帮助决策者客观地评估和比较备选方案,同时考虑到每个选项的正面和负面因素。
模板:
import numpy as npdef topsis(data, weights, impacts):# 数据归一化normalized_data = data / np.sqrt(np.sum(data**2, axis=0))# 加权归一化数据weighted_normalized_data = normalized_data * weights# 理想解和负理想解ideal_solution = np.max(weighted_normalized_data, axis=0)negative_ideal_solution = np.min(weighted_normalized_data, axis=0)# 计算备选方案与理想解和负理想解的距离distances = np.sqrt(np.sum((weighted_normalized_data - ideal_solution)**2, axis=1)) / \np.sqrt(np.sum((weighted_normalized_data - negative_ideal_solution)**2, axis=1))# 考虑权重和影响的得分scores = np.sum(weights * impacts * normalized_data, axis=1)# 综合得分comprehensive_scores = scores / (scores + distances)# 排序并返回结果rankings = np.argsort(comprehensive_scores)[::-1] + 1return rankings# 例子
data = np.array([[3, 2, 5, 4],[4, 1, 2, 8],[1, 3, 4, 6],[2, 4, 3, 5]])weights = np.array([0.25, 0.25, 0.25, 0.25])
impacts = np.array([1, 1, -1, 1])rankings = topsis(data, weights, impacts)
print(rankings)
案例:
极小型指标转化为极大型(正向化):
# 公式:max-x if ('Negative' in name) == True:max0 = data_nor[columns_name[i + 1]].max()#取最大值data_nor[columns_name[i + 1]] = (max0 - data_nor[columns_name[i + 1]]) # 正向化# print(data_nor[columns_name[i+1]])
中间型指标转为极大型(正向化):
# 中间型指标正向化 公式:M=max{|xi-best|} xi=1-|xi-best|/Mif ('Moderate' in name) == True:print("输入最佳值:")max = data_nor[columns_name[i + 1]].max()min = data_nor[columns_name[i + 1]].min()best=input()M=0for j in data_nor[columns_name[i + 1]]:if(M<abs(j-int(best))):M=(abs(j-int(best)))data_nor[columns_name[i + 1]]=1-(abs(data_nor[columns_name[i + 1]]-int(best))/M)#print(data_nor[columns_name[i + 1]])
区间型指标转为极大型(正向化):
# 区间型指标正向化if('Section' in name)==True:print()print("输入区间:")a=input()b=input()a=int(a)b=int(b)max = data_nor[columns_name[i + 1]].max()min= data_nor[columns_name[i + 1]].min()if(a-min>max-b):M=a-minelse:M=max-b#print(data_nor[columns_name[i + 1]][0])cnt=0for j in data_nor[columns_name[i + 1]]:if(j<int(a)):data_nor[columns_name[i + 1]][cnt]=1-(a-j)/Melif (int(a)<= j <=int(b)):data_nor[columns_name[i + 1]][cnt]=1elif (j>b):data_nor[columns_name[i + 1]][cnt]=1-(j-b)/M#print(data_nor[columns_name[i + 1]][cnt])cnt+=1#print(data_nor[columns_name[i + 1]])'''公式:
M = max{a-min{xi},max{xi}-b} xi<a,则xi=1-(a-xi)/M; a<=xi<=b,则xi=1; xi>b,则1-(xi-b)/M
'''
标准化处理:
公式:
def normalization(data_nor):data_nors = data_nor.valuesdata_nors = np.delete(data_nors, 0, axis=1)#去掉第一行squere_A = data_nors * data_nors#矩阵相乘# print(squere_A)sum_A = np.sum(squere_A, axis=0)#按列求和sum_A = sum_A.astype(float)stand_A = np.sqrt(sum_A)#平方根columns_name = data_nor.columns.valuescnt=0for i in columns_name[1:]:#print(data_nor[i])data_nor[i]=data_nor[i]/stand_A[cnt]cnt+=1#print(data_nor)return data_nor
Topsis(优劣解距离法):
公式:
def topsis(data):data_nor=data.copy()data_nor=data_nor.valuesdata_nor = np.delete(data_nor, 0, axis=1)z_max=np.amax(data_nor,axis=0)#每个特征里面挑最大值z_min=np.amin(data_nor,axis=0)#每个特征里面挑最小值#print(z_min)#print(z_max)tmpmaxdist=np.power(np.sum(np.power((z_max-data_nor),2),axis=1),0.5)#最大距离tmpmindist=np.power(np.sum(np.power((z_min-data_nor),2),axis=1),0.5)#最小距离score=tmpmindist/(tmpmindist+tmpmaxdist)#定义得分score = score/np.sum(score)#归一化return score
完整代码:
#coding=gbk
import pandas as pd
import numpy as np
import re
import warnings# 定义文件读取方法
def read_data(file):file_path = fileraw_data = pd.read_excel(file_path, header=0)# print(raw_data)return raw_data# 定义数据正向化
def data_normalization(data):data_nor = data.copy()columns_name = data_nor.columns.values#print(columns_name)for i in range((len(columns_name) - 1)):name = columns_name[i + 1]print("输入这一类数据类型(Positive、Negative、Moderate、Section:)")name=input()# 极小型指标正向化if ('Negative' in name) == True:max0 = data_nor[columns_name[i + 1]].max()#取最大值data_nor[columns_name[i + 1]] = (max0 - data_nor[columns_name[i + 1]]) # 正向化# print(data_nor[columns_name[i+1]])# 中间型指标正向化if ('Moderate' in name) == True:print("输入最佳值:")max = data_nor[columns_name[i + 1]].max()#取最大值min = data_nor[columns_name[i + 1]].min()#取最小值best=input()best=int(float(best))M=0for j in data_nor[columns_name[i + 1]]:if(M<abs(j-int(best))):M=(abs(j-int(best)))data_nor[columns_name[i + 1]]=1-(abs(data_nor[columns_name[i + 1]]-int(best))/M)#print(data_nor[columns_name[i + 1]])# 区间型指标正向化if('Section' in name)==True:print("输入区间:")a=input()b=input()a=int(a)b=int(b)max = data_nor[columns_name[i + 1]].max()min= data_nor[columns_name[i + 1]].min()if(a-min>max-b):M=a-minelse:M=max-b#print(data_nor[columns_name[i + 1]][0])cnt=0for j in data_nor[columns_name[i + 1]]:if(j<int(a)):data_nor[columns_name[i + 1]][cnt]=1-(a-j)/Melif (int(a)<= j <=int(b)):data_nor[columns_name[i + 1]][cnt]=1elif (j>b):data_nor[columns_name[i + 1]][cnt]=1-(j-b)/Mcnt+=1#print(data_nor[columns_name[i + 1]])# print(data_nor)return data_nordef normalization(data_nor):data_nors = data_nor.valuesdata_nors = np.delete(data_nors, 0, axis=1)squere_A = data_nors * data_nors#矩阵相乘# print(squere_A)sum_A = np.sum(squere_A, axis=0)#按列求和sum_A = sum_A.astype(float)stand_A = np.sqrt(sum_A)#开平方columns_name = data_nor.columns.valuescnt=0for i in columns_name[1:]:data_nor[i]=data_nor[i]/stand_A[cnt]#每个元素除以相对应的平方根cnt+=1#print(data_nor)return data_nor# 定义计算熵权方法
def entropy_weight(data_nor):columns_name = data_nor.columns.valuesn = data_nor.shape[0]E = []for i in columns_name[1:]:# 计算信息熵# print(i)data_nor[i] = data_nor[i] / sum(data_nor[i])data_nor[i] = data_nor[i] * np.log(data_nor[i])data_nor[i] = data_nor[i].where(data_nor[i].notnull(), 0)# print(data_nor[i])Ei = (-1) / (np.log(n)) * sum(data_nor[i])E.append(Ei)# print(E)# 计算权重W = []for i in E:wi = (1 - i) / ((len(columns_name) - 1) - sum(E))W.append(wi)# print(W)return W# 计算得分
def entropy_score(data, w):data_s = data.copy()columns_name = data_s.columns.valuesfor i in range((len(columns_name) - 1)):name = columns_name[i + 1]data_s[name] = data_s[name] * w[i]return data_sdef topsis(data):data_nor=data.copy()data_nor=data_nor.valuesdata_nor = np.delete(data_nor, 0, axis=1)z_max=np.amax(data_nor,axis=0)#每个特征里面挑最大值z_min=np.amin(data_nor,axis=0)#每个特征里面挑最小值#print(z_min)#print(z_max)tmpmaxdist=np.power(np.sum(np.power((z_max-data_nor),2),axis=1),0.5)#最大距离tmpmindist=np.power(np.sum(np.power((z_min-data_nor),2),axis=1),0.5)#最小距离score=tmpmindist/(tmpmindist+tmpmaxdist)#定义得分score = score/np.sum(score)#归一化return scoreif __name__ == "__main__":file = 'filepath' # 声明数据文件地址data = read_data(file) # 读取数据文件data_nor = data_normalization(data) # 数据正向化,生成后的数据data_norprint("\n正向化后的数据:")print(data_nor)data_nor=normalization(data_nor)print("\n标准化后的数据:")print(data_nor)score=topsis(data_nor)print("\n得分:")print(score)score=pd.DataFrame(score)score.columns=["得分"]data=pd.DataFrame(data)data=pd.concat([data,score],axis=1)print(data)
结果: