建模笔记——熵权法(Python实现)

一、模型介绍

熵权法是一种通过对已知数据的处理,从而获得影响因子权重的方法,其基本思路是根据指标变异性的大小来确定客观权重。

熵权法的优点在于其根据各项指标指标值的变异程度来确定指标权数的,是一种客观赋权法,避免了人为因素带来的偏差。相对那些主观赋值法,精度较高客观性更强,能够更好的解释所得到的结果。

熵权法的缺点在于忽略了指标本身重要程度,有时确定的权重会与预期的结果相差甚远,同时熵值法不能减少评价指标的维数,也就是熵权法符合数学规律具有严格的数学意义,但往往会忽视决策者主观的意图。并且如果指标值的变动很小或者很突然地变大变小,熵权法使用时会存在一定的局限。

二、基本思路与步骤

(1)指标正向化

不同的指标代表含义不一样,有的指标越大越好,称为正向指标;有的指标越小越好,称为负向指标;而有些指标在某个点或者区间是最好的,称为适度指标。为方便评价,应把所有指标进行同向化处理。

X=(x_{ij})

 正向指标:

{x_{ij}^{'}}=x_{ij}

 负向指标:

{x_{ij}^{'}}=max(x_{ij})-x_{ij}

适度指标:

{x_{ij}^{'}}=1-\frac{\left |{x_{ij}}-a \right |}{max(\left |{x_{ij}}-a \right |)}

(2)数据标准化

将指标按比例缩放,使它们落在特定的区间,从而可以去除量纲的影响,使得不同单位或者量级的指标能够进行比较、加权。

这里采用常用的离差标准化法对数据进行处理:

{x_{ij}^{*}}=\frac{​{x_{ij}^{'}}-min({x_{j}^{'}})}{max({x_{j}^{'}})-min({x_{j}^{'}})}

(3)计算信息熵

根据信息论中信息熵的定义,一组数据的信息熵计算公式为:

E_{j}=-\frac{1}{lnn}\sum_{j=1}^{n}p_{ij}lnp_{ij}

p_{ij}=Y_{ij}/\sum_{j=1}^{n}Y_{ij}

 如果:

p_{ij}=0

则:

\lim_{p_{ij}\rightarrow 0}p_{ij}lnp_{ij}=0

(4)确定各指标的权重并计算得分

通过信息熵计算各指标的权重:

W_{i}=\frac{1-E_{i}}{k-\sum E_{i}}(i=1,2,..,k)

三、代码实现

数据表格式:

建模笔记——熵权法(Python实现)_第1张图片

这里指标名后缀用Positive(正向指标)、Negative(负向指标)、Moderate(适度指标)来对指标类型进行标识。 

Python代码如下:

import pandas as pd
import numpy as np
import re
#定义文件读取方法
def read_data(file):
    file_path=file
    raw_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
    for i in range((len(columns_name)-1)):
        name=columns_name[i+1]
        #print(name)
        #正向指标直接标准化
        if ('Positive' in name)==True:
            max=data_nor[columns_name[i+1]].max()
            min=data_nor[columns_name[i+1]].min()
            data_nor[columns_name[i+1]]=(data_nor[columns_name[i+1]]-min)/(max-min)
            #print(data_nor[columns_name[i+1]])

        #负向指标先正向化、在标准化
        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]])#正向化


            max=data_nor[columns_name[i+1]].max()
            min=data_nor[columns_name[i+1]].min()
            data_nor[columns_name[i+1]]=(data_nor[columns_name[i+1]]-min)/(max-min)#标准化
            #print(data_nor[columns_name[i+1]])

        #适度指标先正向化、在标准化
        if ('Moderate' in name)==True:
            try:
                val_range= re.search(r'.*[\((](.*),(.*)[\))]',name)
                val_down= float(val_range.group(1))
                val_up= float(val_range.group(2))
                val_op=(val_up+val_down)/2
            except:
                val_range= re.search(r'.*[\((](.*)[\))]',name)
                val_op= float(val_range.group(1))
            #print(val_op)
            data_nor[columns_name[i + 1]] = 1-(abs(data_nor[columns_name[i + 1]]-val_op)/(abs(data_nor[columns_name[i + 1]]-val_op).max()))  #正向化

            max=data_nor[columns_name[i+1]].max()
            min=data_nor[columns_name[i+1]].min()
            data_nor[columns_name[i+1]]=(data_nor[columns_name[i+1]]-min)/(max-min)#标准化
            #print(data_nor[columns_name[i+1]])

    #print(data_nor)
    return data_nor


#定义计算熵权方法
def entropy_weight(data_nor):
    columns_name=data_nor.columns.values
    n=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.values
    for i in range((len(columns_name)-1)):
        name=columns_name[i+1]
        data_s[name]=data_s[name]*w[i]
    return data_s





file='data.xls'#声明数据文件地址
data=read_data(file)#读取数据文件
data_nor=data_normalization(data)#数据标准化、正向化,生成标准化后的数据data_nor
W=entropy_weight(data_nor)#计算熵权权重
data_s=entropy_score(data,W)#计算赋权后的得分,使用原数据计算
data_nor_s=entropy_score(data_nor,W)

W.insert(0,'熵权法权重')#将结果保存为csv
W0=pd.DataFrame(W).T
data_s.to_csv('熵权法得分结果(原始数据).csv',index=0)
W0.to_csv('熵权法得分结果(原始数据).csv', mode='a', header=False,index=0)
data_nor_s.to_csv('熵权法得分结果(标准化数据).csv',index=0)
W0.to_csv('熵权法得分结果(标准化数据).csv', mode='a', header=False,index=0)

你可能感兴趣的:(统计模型,python,numpy,数据分析)