TOPSIS(优劣解距离法)【附Python实现代码及可视化代码】

news2024/11/29 13:53:14

目录

一、指标正向化

1.极小型指标->极大型指标

2.中间型指标->极大型指标

3.区间型指标->极大型指标

二、标准化处理

三、计算得分并归一化(不带权重)

四、计算得分并归一化(带权重)

熵权法

1)判断输入的矩阵是否存在负数

2)计算第j项指标下第i个样本所占的比重,并将其看作相对熵计算中用到的概率

3)计算每个指标的信息熵,并计算信息效用值,并归一化得到每个指标的熵权

五、代码

 5.1 指标正向化

 5.2 标准化处理

 5.3 计算得分并排序(人工赋权重)

 5.4 熵权法

5.5 数据可视化


TOPSIS法是一种常用的综合评价方法,其能充分利用原始数据的信息,其结果能精确反应各评价方案之间的差距。

用TOPSIS法来评定一个人是不是值得恋爱。比如,现在有4个人,他们分别为Terry,xiaofang,smike,jerry.以下为根据他们身边的好朋友对他们的评价得分:

简单的评分方法是直接按评价得分高低排名评分:

不过要用修正后的排名,因为评分越高越好

但是这样会出现一个问题,可以随便修改得分,只要排名不变,评分也不会改变。

所以,我们不能直接按得分排名评价,要构造计算评分的公式:

TOPSIS法步骤如下:

一、指标正向化

好友评分是越大(高)越好,这样的指标称为极大型指标(效益型指标)。

恋爱次数是越少(低)越好,这样的指标称为极小型指标(成本型指标)

中间型指标:指标值既不要太大也不要太小,取某特定值最好(如水质量评估 PH 值 )

区间型指标:指标值落在某个区间内最好,例如人的体温在36°~37°这个区间比较好。

所以,我们必须的统一指标类型,将所有的指标转化为极大型,即指标正向化。

1.极小型指标->极大型指标

公式:

如果所有的元素均为正数,那么也可以使用

2.中间型指标->极大型指标

举例:

3.区间型指标->极大型指标

 上面不好理解也可以看下面这个公式

二、标准化处理

为了消去不同指标量纲的影响,需要对已经正向化的矩阵进行标准化处理。

比如:

三、计算得分并归一化(不带权重)

归一化之后就可以根据数值大小进行排名

区别归一化和标准化:

归一化的目的:为了让结果更容易解释,对结果有一个更加清晰直观的印象。

标准化的目的:消除量纲的影响。

四、计算得分并归一化(带权重)

如何计算权重?

基于熵权法的赋值

熵权法

熵权法是一种客观赋权方法

原理:

指标的变异程度越小,所反映的信息量也越少,其对应的权值也应该越低。

如何度量信息量的大小?

越有可能发生的事情,信息量越少,

越不可能发生的事情,信息量就越多。

怎么衡量事情发生的可能性大小 ?

概率

如何度量信息量的大小?

信息熵越大,则它的值能补充的信息量越大,说明这个值已有的信息量越小,所以信息量越小

熵权法计算步骤:

1)判断输入的矩阵是否存在负数

如果存在负数,就要重新标准化到非负区间。

2)计算第j项指标下第i个样本所占的比重,并将其看作相对熵计算中用到的概率

3)计算每个指标的信息熵,并计算信息效用值,并归一化得到每个指标的熵权

五、代码

import numpy as np
import pandas as pd


data = pd.DataFrame(
        {'人均专著': [0.1, 0.2, 0.4, 0.9, 1.2], 
         '生师比': [5, 6, 7, 10, 2], 
         '科研经费': [5000, 6000, 7000, 10000, 400],
         '逾期毕业率': [4.7, 5.6, 6.7, 2.3, 1.8]}, 
          index=['院校' + i for i in list('ABCDE')])

 对五所研究生院进行评价,构造数据如下:

 5.1 指标正向化

# 指标正向化
# 结合公式理解代码
# 需要根据题目选择具体的处理方法


# 极小型转为极大型指标
def dataDirection_1(datas, offset=0):
    def normalization(data):
        return 1 / (data + offset)

    return list(map(normalization, datas))


# 中间型指标转为极大型指标
def dataDirection_2(datas, x_min, x_max):
    def normalization(data):
        if data <= x_min or data >= x_max:
            return 0
        elif data > x_min and data < (x_min + x_max) / 2:
            return 2 * (data - x_min) / (x_max - x_min)
        elif data < x_max and data >= (x_min + x_max) / 2:
            return 2 * (x_max - data) / (x_max - x_min)

    return list(map(normalization, datas))

# 区间型指标转为极大型指标
# [x_min, x_max]最佳稳定区间, [x_minimum, x_maximum]容忍区间
def dataDirection_3(datas, x_min, x_max, x_minimum, x_maximum):  
    def normalization(data):
        if data >= x_min and data <= x_max:
            return 1
        elif data <= x_minimum or data >= x_maximum:
            return 0
        elif data > x_max and data < x_maximum:
            return 1 - (data - x_max) / (x_maximum - x_max)
        elif data < x_min and data > x_minimum:
            return 1 - (x_min - data) / (x_min - x_minimum)

    return list(map(normalization, datas))

例题数据处理:

# 极小型指标转为极大型
minimum_list = dataDirection_1(data.loc[:,"逾期毕业率"])
minimum_array = np.array(minimum_list)
minimum_4f = np.round(minimum_array, 6)
print(minimum_4f)

# 区间型指标转为极大型
maximum_list = dataDirection_3(data.loc[:,"生师比"], 5, 6, 2, 12)
maximum_array = np.array(maximum_list)
maximum_4f = np.round(maximum_array, 6)
print(maximum_4f)

结果:
[0.212766 0.178571 0.149254 0.434783 0.555556]
[1.       1.       0.833333 0.333333 0.      ]
# 指标正向化结果
index_Isotropy = pd.DataFrame()
index_Isotropy["人均专著"] = data["人均专著"]
index_Isotropy["生师比"] = maximum_4f
index_Isotropy["科研经费"] = data["科研经费"]
index_Isotropy["逾期毕业率"] = minimum_4f
print(index_Isotropy)

 5.2 标准化处理

# 这里采用归一化,数据处于0-1之间,便于可视化
data_normalization = index_Isotropy / np.sqrt((index_Isotropy ** 2).sum())
print(data_normalization)

 5.3 计算得分并排序(人工赋权重)

def topsis(data, weight=None):


    # 最优最劣方案(最大值Z^+ 和 最小值)
    Z = pd.DataFrame([data.max(), data.min()], index=['正理想解', '负理想解'])

    # 距离
    weight = entropyWeight(data) if weight is None else np.array(weight)
    Result = data.copy()
    Result['正理想解'] = np.sqrt(((data - Z.loc['正理想解']) ** 2 * weight).sum(axis=1)) # 评价对象与最大值的距离
    Result['负理想解'] = np.sqrt(((data - Z.loc['负理想解']) ** 2 * weight).sum(axis=1))

    # 综合得分指数
    Result['综合得分指数'] = Result['负理想解'] / (Result['负理想解'] + Result['正理想解'])  
    Result['排序'] = Result.rank(ascending=False)['综合得分指数']

    return Result, Z, weight

# 人工赋权重的结果
weight = [0.2, 0.3, 0.4, 0.1]
Result, Z, weight = topsis(data_normalization, weight)

 5.4 熵权法

def entropyWeight(data):
    data = np.array(data)
    # 计算第j个指标下第i个样本所占的比重,相对熵计算中用到的概率
    P = data / data.sum(axis=0)  # 压缩行
    # 计算熵值
    E = np.nansum(-P * np.log(P) / np.log(len(data)), axis=0)
    # 信息效用值
    d = (1 - E)
    # 计算权系数
    W = d / d.sum()
    return W

entropyWeight(data)

结果:
array([0.41803075, 0.14492264, 0.28588943, 0.15115718])

# 将计算出来的权重代入5.3计算就可以

5.5 数据可视化

这里是对原始数据归一化后以及计算出来的正负理想解进行可视化,便于观察比较各院校特征

使用了雷达图

# 把归一化的结果列的顺序改一下,把‘生师比’放第一个,便于下图展示,不改也可以
data_normalization=data_normalization[['生师比','人均专著',  '逾期毕业率', '科研经费']]
data_normalization
from math import pi
import matplotlib.pyplot as plt


# 目标数量
categories = list(data_normalization)[0:]
N = len(categories)

# 角度
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]

# 绘图初始化
plt.figure(dpi=150)
plt.style.use('ggplot')
ax = plt.subplot(111, polar=True)

# 设置第一处
ax.set_theta_offset(pi / 2)  # 设置最上面为0°
ax.set_theta_direction(-1)  # 设置正方形为顺时针

# 添加背景信息
plt.title("研究生院试评估")
plt.xticks(angles[:-1], categories)  # 改变轴标签rotation = 30
plt.xticks(rotation = pi/4,fontsize=6)
ax.set_rlabel_position(30)   # 极径标签显示位置
# ax.set_rgrids(np.arange(0.1,0.9,0.1))
plt.yticks(np.arange(0.1,0.9,0.1), ["0.1", "0.2", "0.3","0.4","0.5","0.6","0.7","0.8"], color="grey", size=5)  # 设置极径标签区间
plt.ylim(0, 0.8)  # 设置极径范围

# 添加数据图

# 第一个
values = data_normalization.loc["院校A"].values.flatten().tolist()
values += values[:1]  # 首尾相连
ax.plot(angles, values, linewidth=1, linestyle='solid', color='#d62728',marker='.',markersize=4,label="院校A")
ax.fill(angles, values, '#d62728', alpha=0.2)  # 填充线条

# 第二个
values = data_normalization.loc["院校B"].values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid',color='#1f77b4',marker='.',markersize=4, label="院校B")
ax.fill(angles, values, '#1f77b4', alpha=0.2)

# 第三个
values = data_normalization.loc["院校C"].values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid', color='#9467bd',marker='.',markersize=4,label="院校C")
ax.fill(angles, values, '#9467bd', alpha=0.2)

# 第四个
values = data_normalization.loc["院校D"].values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid',color='#7f7f7f', marker='.',markersize=4, label="院校D")
ax.fill(angles, values, '#7f7f7f', alpha=0.2)

# 第五个
values = data_normalization.loc["院校E"].values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid',color='#ff7f0e',marker='.',markersize=4, label="院校E")
ax.fill(angles, values, '#ff7f0e', alpha=0.2)

# 最优解
values =Z.loc["正理想解"].values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid',color='#2ca02c',marker='.',markersize=4, label="最优解")
ax.fill(angles, values, '#2ca02c', alpha=0.2) 

# 最劣解
values =Z.loc["负理想解"].values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid',color='#e377c2',marker='.',markersize=4, label="最劣解")
ax.fill(angles, values, '#e377c2', alpha=0.2) 

# 添加图例
plt.legend(loc='upper right', bbox_to_anchor=(1.5, 1))

# 显示
plt.show()

 可视化结果如下:

参考资料:

原理部分参考了清风数模视频和一篇博客,具体哪篇之前写的时候忘记下来了

代码部分参考了下面知乎这篇,原理讲的也很好,不过这篇没有雷达图的代码,本文补充了这部分代码

TOPSIS法(优劣解距离法)介绍及 python3 实现 - 知乎 (zhihu.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/589939.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过 Wacom 的 Project Mercury 提高远程办公效率

过去几年中&#xff0c;我们的工作方式发生了翻天覆地的变化。疫情加快了对远程办公和协作的采纳&#xff0c;导致人们更加依赖技术来联系团队和提高工作效率。 但是&#xff0c;那些依靠专门硬件和软件来完成工作的创作者呢&#xff1f;艺术家、设计师和开发人员需要使用专门…

34 KVM管理设备-管理虚拟磁盘

文章目录 34 KVM管理设备-管理虚拟磁盘34.1 概述34.2 操作步骤 34 KVM管理设备-管理虚拟磁盘 34.1 概述 虚拟磁盘类型主要包含virtio-blk、virtio-scsi、vhost-scsi等。virtio-blk模拟的是一种block设备&#xff0c;virtio-scsi和vhost-scsi模拟的是一种scsi设备。 virtio-b…

window部署redis集群

1.下载Redis-x64-3.2.100.zip 下载网址&#xff1a;https://github.com/microsoftarchive/redis 百度网盘下载&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;j2js redis版本一定要大于3.0&#xff0c;原因&#xff1a;windows暂不支持redis-cli创建集群&#xff0c;…

TPP0100泰克无源电压探头

tektronix泰克TPP0100 和 TPP0101无源电压探头是输入电阻为 10 M? 的 100 MHz、10X 无源电压探头。这些探头是和 1 MΩ/13 pF (TPP0100) 和 1 MΩ/20 pF (TPP0101) 输入的 BNC示波器搭配 使用。 tektronix泰克TPP0100无源电压探头特点 带宽 直流至 100 M…

Day5 统计回文、连续最大和

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; C/C相关题解 &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 16.11.17 文章目录 选择题1.C指针/链表/结构 编程题1.统计回文2.连续最大和 选择题 1.C指针/链表/结构 题目&#xff1a;下面两个结…

MySQL 性能调优及生产实战篇终版

前言为什么会查询慢&#xff1f;优化数据访问查询数据低效原因是否请求了不需要的数据 优化执行过程查询缓存查询优化处理语法解析器查询优化器优化器的优化策略优化器的优化类型关联查询排序优化 大数据量查询优化优化 COUNT 查询优化关联查询优化子查询优化 LIMIT 分页优化 u…

Laetus控制器维修20C-A323包装机控制模块

LAETUS 旗下系列有&#xff1a; ARGUS 、 POLYPHEM 、 INSPECT 等均可维修。Laetus GmbH控制器维修28C-A353&#xff0c;设备控制模块维修。 Laetus GmbH部分产品维修型号&#xff1a; Laetus 2D COSI wt &#xff1b; Laetus 2D COSI wt Laetus TDK Lambda HK15 Laetus 2D-…

别再瞎考证了!关于网络安全行业的证书,看完这篇,明明白白考证

有相关证书会让你的职业生涯锦上添花&#xff0c;实战技术能力必不可少。 温馨提示&#xff1a; 1、不满足条件的高校学生群体&#xff0c;可以直接报名考取NISP二级证书&#xff0c;满足CISP认证要求后&#xff0c;免考试按规定更换CISP证书&#xff0c;为毕业后从事网络安全…

一切从“简”,解放IT运维人员

运维人的神技 运维既是个技术活儿也是个苦差事&#xff0c;而运维人员被期望有着无限的技能&#xff1a;主机、存储、网络、操作系统样样精通&#xff0c;而且还要会写SQL、shell、开发语言java、.net、python等等&#xff0c;对业务更是门清&#xff0c;对各个用户的脾气喜好也…

vector常见接口的使用(基于c++标准库中的STL)

前言 vector是STL中的重要容器&#xff0c;在平时使用中较常见。学会使用它以及了解它的核心原理对于我们学习它是很有帮助的。vector是可以动态增长的数组。vector可以像数组一样进行随机访问&#xff0c;这是vector最大的优势之一&#xff0c;因为支持随机访问就间接的支持了…

TRUNCATE TABLE t 和DELETE FROM t的区别

背景 最近再工作中,遇到一个问题,就是再代码执行过程中,出现异常时并不会去回滚代码.导致数据不一致,最初以为是Transactional这个注解没有生效 Spring中什么时候Transactional会失效 因为Spring事务是基于代理来实现的,所以某个加了Transactional的方法只有是被代理对象调用…

APP测试面试题快问快答(二)

1.请问App测试的主要内容包含&#xff1f; 功能测试&#xff1a; 业务逻辑正确性测试&#xff1a;依据产品文档->测试用例编写。 界面的测试 界面测试&#xff1a;依据产品UI设计文档&#xff08;高保真图&#xff0c;原型图&#xff09;。 升级&#xff0c;安装&#…

研发工程师玩转Kubernetes——定时任务

定时任务是指可以制定周期的任务&#xff0c;比如每周二0点1分执行一次。在《研发工程师玩转Kubernetes——非定时任务》中&#xff0c;我们介绍了单次执行的任务。现在我们只要对其清单稍作修改&#xff0c;就可以实现定时任务。 # wrk_cronjob.yaml apiVersion: batch/v1 ki…

【论文阅读】SeaD: End-to-end Text-to-SQL Generation with Schema-aware Denoising

【论文阅读】SeaD: End-to-end Text-to-SQL Generation with Schema-aware Denoising 文章目录 【论文阅读】SeaD: End-to-end Text-to-SQL Generation with Schema-aware Denoising1. 来源2. 介绍3. 模型3.0 问题定义3.1 采样公式3.2 带指针的 Transformer3.3 模式感知去噪&am…

低代码平台或零代码平台靠谱吗?15 年的老程序员来给大家剖析一下

提到低代码平台或者零代码平台靠谱吗&#xff1f;咱们首先得先认识一下低代码和零代码平台。 一、什么是低代码开发平台呢&#xff1f; 低代码的含义是少写代码并不是不写代码&#xff0c;面向的用户群体还是编程人员&#xff0c;传统的快速开发平台、在线开发平台、OA办公系统…

Python中Pandas库中的DataFrame数据结构创建举例

Python中Pandas库的DataFrame数据结构创建举例 DataFrame的数据结构是Python数据分析中重要应用数据类型。本文将重点介绍DataFrame的创建。 1.DataFrame的创建 创建DataFrame的方法使用pandas.DataFrame&#xff0c;向该方法传入字典即可创建DataFrame。 传入的字典的key对应E…

【HAL库】STM32F407----CAN通信----过滤器配置

【HAL库】STM32F407----CAN通信----基本原理 【HAL库】STM32F407----CAN通信----电路图 【HAL库】STM32F407----CAN通信----中断详解 【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验 一、STM32F407----CAN过滤器----简介 在CAN协议里&#xff0c;报文的标识符不代表节…

纯vue 获取usb串口,实现电子秤的对接

说明&#xff1a;解决生产上过秤重量手动输入出错问题 效果图&#xff1a; 一&#xff1a;代码部分 1、创建一个名字为seriaport.js文件&#xff08;随便定义&#xff0c;为下面页面引入使用&#xff09; export default class MySerialPort {constructor() {this.state {po…

超级干货!前端入门先学什么?前端自学路线分享!

各位同学&#xff0c;下午好~之前给大家分享了前端岗位的面试题&#xff0c;小源能看的出来&#xff0c;还是有不少同学想入行前端的&#xff01;那除了会面试&#xff0c;还要有充足丰富的知识储备&#xff0c;这样才能拿下工作&#xff01; 好程序员今天就给大家整理了一份前…

C++进阶 —— set

目录 一&#xff0c;set介绍 二&#xff0c;set使用 一&#xff0c;set介绍 set是按照特定次序存储元素的关联式容器&#xff0c;元素不可重复&#xff1b;set中的元素不能在容器中修改(元素总是const)&#xff0c;但是可从容器中插入和删除它们&#xff1b;set中的元素总是按…