TOPSIS 法是一种常用的组内综合评价方法,能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的差距。基本过程为基于归一化后的原始数据矩阵,采用余弦法找出有限方案中的最优方案和最劣方案,然后分别计算各评价对象与最优方案和最劣方案间的距离,获得各评价对象与最优方案的相对接近程度,以此作为评价优劣的依据。该方法对数据分布及样本含量没有严格限制,数据计算简单易行。
模型理论
TOPSIS法的基本思想是:对原始数据同趋势后构建归一化矩阵,计算评价对象与最优向量和最劣向量的差异,以此测度评价对象的差异。假设有n个评价对象,m个指标,TOPSIS法的基本步骤为:
原始数据同趋势化
区分指标体系中的指标类别(高优或低优),并根据不同类型的指标需要按照不同的公式进行正向化处理。构建n行m列的矩阵Xij,矩阵中X表示第i个对象的第j个指标的值。
构建标准化矩阵
Z_{ij}=\frac{X_{ij}}{\sqrt{\sum^n_{k=1}(X_{ij})^2}}
确定理想解
正理想解Z^+_j=\left\{\begin{aligned} &\max_iz^+_{ij}\\ &\min_iz^-_{ij} \end{aligned}\right.\quad 负理想解Z^-_j=\left\{\begin{aligned} &\min_iz^+_{ij}\\ &\max_iz^-_{ij} \end{aligned}\right.
计算各评价指标与最优及最劣向量之间的差距
D^+_i=\sqrt{\sum^m_{j=1}w_j(Z_j^+-z_{ij})^2},D^-_i=\sqrt{\sum^m_{j=1}w_j(Z_j^--z_{ij})^2}
评价对象与最优方案的接近程度
C_i=\frac{D_i^-}{D_i^++D_i^-}
代码示例
# 综合评价
class ComprehensiveEvaluation:
@staticmethod # 标准化矩阵
def normalizeMatrix(matrix:np.ndarray):
min_z=np.min(matrix,axis=0)
max_z=np.max(matrix,axis=0)
z=(matrix-min_z)/(max_z-min_z)
z=np.where(z!=0,z,z+0.001)
return z
def __init__(self,x:np.ndarray,labels=None,indexs=None):
self.x=x # 数据矩阵
self.labels=labels # 数据标签(指标)
self.indexs=indexs # 数据索引
self.n,self.m=self.x.shape # 个体数,指标数
self.z=self.normalizeMatrix(self.x) # 标准化矩阵
class TOPSIS(ComprehensiveEvaluation):
@staticmethod # 正向化矩阵
def positiveizeMatrix(matrix:np.ndarray):
return matrix/np.sqrt(np.sum(np.power(matrix,2),axis=0))
def decideWeight(self,useWeight):
if useWeight=='Entropy':
return self.entropy.w
elif type(useWeight)==type(None):
return np.ones(self.m)
else:
return useWeight
def __init__(self,x:np.ndarray,useWeight=None,labels=None,indexs=None):
super().__init__(x,labels,indexs)
self.entropy=Entropy(x,labels,indexs) # 熵权法
self.weight=self.decideWeight(useWeight) # 使用的权重
self.z=self.positiveizeMatrix(self.z) # 经过正向化和标准化的矩阵
self.best_pos=np.abs(np.max(self.z,axis=0)) # 正理想解
self.best_neg=np.abs(np.min(self.z,axis=0)) # 负理想解
# 正理想解距离
self.D_pos=np.sqrt(np.sum(self.weight*np.power(self.best_pos-self.z,2),axis=1))
# 负理想解距离
self.D_neg=np.sqrt(np.sum(self.weight*np.power(self.best_neg-self.z,2),axis=1))
# 结果评估
self.C=self.D_neg/(self.D_pos+self.D_neg)
def show(self):
print('指标权重计算:')
columns=['信息熵值e','信息效用值d','权重']
data=np.c_[np.reshape(self.entropy.e,(self.entropy.e.size,1)),
np.reshape(self.entropy.d,(self.entropy.d.size,1)),
np.reshape(self.entropy.w,(self.entropy.w.size,1))]
if type(self.labels)==type(None):
table=pd.DataFrame(data,columns=columns)
label=np.arange(0,self.entropy.w.size)
else:
table=pd.DataFrame(data,columns=columns,index=self.labels)
label=self.labels.values
display(table)
print('TOPSIS评价法计算结果:')
columns=['正理想解距离','负理想解距离','综合得分','排名']
rank_=np.argsort(-self.C)
rank=np.copy(rank_)
for i in range(0,rank.size):
rank[rank_[i]]=i
data=np.c_[np.reshape(self.D_pos,(self.D_pos.size,1)),
np.reshape(self.D_neg,(self.D_neg.size,1)),
np.reshape(self.C,(self.C.size,1)),
np.reshape(rank+1,(rank.size,1))]
if type(self.indexs)==type(None):
table=pd.DataFrame(data,columns=columns)
else:
table=pd.DataFrame(data,columns=columns,index=self.indexs)
display(table)
print('中间值展示:')
columns=['正理想解','负理想解']
data=np.c_[np.reshape(self.best_pos,(self.best_pos.size,1)),
np.reshape(self.best_neg,(self.best_neg.size,1))]
if type(self.labels)==type(None):
table=pd.DataFrame(data,columns=columns)
label=np.arange(0,self.entropy.w.size)
else:
table=pd.DataFrame(data,columns=columns,index=self.labels)
label=self.labels.values
display(table)
file='E:\DEV\python\math\data\TOPSIS.xlsx'
data=pd.read_excel(file,index_col=0)
data.values[:,2:]=-data.values[:,2:]
tourist=TOPSIS(data.values,'Entropy',labels=data.columns,indexs=data.index)
tourist.show()
指标权重计算: 信息熵值e 信息效用值d 权重 风景 0.797092 0.202908 0.257997 人文 0.821744 0.178256 0.226653 拥挤程度 0.797600 0.202400 0.257352 票价 0.797092 0.202908 0.257997 TOPSIS评价法计算结果: 正理想解距离 负理想解距离 综合得分 排名 风景地点 A 0.432467 0.553105 0.561202 1.0 B 0.512573 0.343868 0.401508 5.0 C 0.409230 0.360506 0.468350 4.0 D 0.440231 0.488308 0.525888 2.0 E 0.475013 0.452429 0.487824 3.0 中间值展示: 正理想解 负理想解 风景 0.730297 0.000730 人文 0.749268 0.000749 拥挤程度 0.766261 0.000766 票价 0.730297 0.000730