优劣解距离法(TOPSIS)的Python实现方式

        TOPSIS是一种常用的综合评价方法,能充分利用原始数据的信息,反映各个评价方案之间的差异。在层次分析法中,我们往往不知道指标的数据,需要主观(专家)打分,且评价的决策层不能太多,而TOPSIS方法对数据分布以及样本含量没有严格限制,计算方式简易。

        第一步,为了保证评分是越大越好,需将原始矩阵正向化。

        指标计算方式的理解:极小型就是倒转数据,中间型就是距离中间点距离的倒转,区间型则要分类,靠左就是距离下限的距离的倒转,靠右就是距离上限距离的倒转(越近越好)。下面来看看代码吧:

#极小型指标
def func1(data):
    return max(data) - data

#中间型指标
def func2(data):
    x_best = eval(input('请输入最佳数值:'))    #给出最佳数值
    M = max(np.abs(data-x_best))
    return 1-np.abs(data-x_best)/M

#区间型指标
def func3(data):
    a = eval(input('请输入最佳区间下限:'))
    b = eval(input('请输入最佳区间上限:'))
    M = max(a-min(data),max(data)-b)
    new = []
    for x in data:
        if x<a:
            new.append(1-(a-x)/M)
        elif a<=x<=b:
            new.append(1)
        else:
            new.append(1-(x-b)/M)
    return np.array(new).reshape(1,-1)

        第二步,将得到的正向化矩阵标准化,目的是为了消除不同指标量纲的影响。当然,标准化的方法有很多种,这里我们采用的是前人论文中最常用的一种标准化方法。

        将其转化为代码:

def normal_func(data):
    for i in range(data.shape[1]):
        z = data[:,i]/pow(np.sum(pow(data[:,i],2)),0.5)
        data[:,i] = z
    return data

        第三步,计算得分并归一化。在一维的指标中,例如甲、乙、丙、丁参加考试,分别答对10、8、5、3道题,我们常常会将答对最多的人设定为满分,答对最少的人定义为0分,而乙的分数则为:

score=\frac{8-3}{10-3}\times\100

        我们可理解分母就是该指标与最大值的距离和最小值的距离之和,那么多维指标也是同理。

def func_z(data):
    z_max = []
    z_min = []
    s = []
    final = []
    for i in range(data.shape[1]):
        z_max.append(max(data[:,i]))
        z_min.append(min(data[:,i]))
    z_max = np.array(z_max)
    z_min = np.array(z_min)
    for j in range(data.shape[0]):     #计算得分
        D_max = pow(sum(pow(z_max-data[j,:],2)),0.5)
        D_min = pow(sum(pow(z_min-data[j,:],2)),0.5)
        s.append(D_min/(D_max+D_min))
    for k in range(len(s)):           #归一化
        final.append(s[k]/sum(s))
    return np.array(final).reshape(-1,1)

        让我们看一下数据代入的具体实现吧,老规矩三件套pandas、numpy、matplotlib:

import pandas as pd
import numpy as np
data = pd.read_excel('data.xlsx')

#提取每一列指标的数据
data1 = data['含氧量(ppm)'].values
data2 = data['PH值'].values
data3 = data['细菌总数(个/mL)'].values
data4 = data['植物性营养物量(ppm)'].values

#正向化
data1 = data1.reshape(-1,1)
data2 = func2(data2).reshape(-1,1)
data3 = func1(data3).reshape(-1,1)
data4 = func3(data4).reshape(-1,1)

#标准化
#组成新的正向化后的矩阵
data_positive = np.concatenate((data1,data2,data3,data4),axis=1)    #axis=1是按行的方向
data_normal = normal_func(data_positive)

#计算得分
score = func_z(data_normal)


代码不足:①我们可以按照评分从大到小画出不同样本的评分折线图,可视化效果更好

                  ②TOPSIS默认每个指标是相同权重的,我们可以结合AHP、熵权法来加权


本文主体思路借鉴某视频,侵权即删。

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值