熵值法的Python实现

一、基本原理

在信息论中,熵是对不确定性的一种度量。信息量越大,不确定性就越小,熵也就越小;信息量越小,不确定性越大,熵也越大。

根据熵的特性,可以通过计算熵值来判断一个事件的随机性及无序程度,也可以用熵值来判断某个指标的离散程度,指标的离散程度越大,该指标对综合评价的影响(权重)越大,其熵值越小。

二、熵值法步骤

  1. 选取n个国家,m个指标,则
    image.png
    为第i个国家的第j个指标的数值(i=1, 2…, n; j=1,2,…, m);

  2. 指标的归一化处理:异质指标同质化

由于各项指标的计量单位并不统一,因此在用它们计算综合指标前,先要对它们进行标准化处理,即把指标的绝对值转化为相对值,并令
image.png
,从而解决各项不同质指标值的同质化问题。而且,由于正向指标和负向指标数值代表的含义不同(正向指标数值越高越好,负向指标数值越低越好),因此,对于高低指标我们用不同的算法进行数据标准化处理。其具体方法如下:

正向指标:

image.png
负向指标:

image.png

image.png
为第i个国家的第j个指标的数值(i=1, 2…, n; j=1, 2,…, m)。为了方便起见,归一化后的数据仍记为[图片上传失败…(image-5bd2d6-1545816016204)]

  1. 计算第j项指标下第i个国家占该指标的比重:

image.png
4. 计算第j项指标的熵值:

image.png
其中
image.png
. 满足
image.png
;

  1. 计算信息熵冗余度:

image.png
6. 计算各项指标的权值:

image.png
7. 计算各国家的综合得分:

image.png
注:对正逆指标归一化的时候如果采用的方法不一样,正指标归一化得到的值会大一些,逆指标的归一化得到的值会小一些,然后算权重,逆指标对应的权重也会相应的小,从而逆指标对应的得分也小些,就相当于对逆指标进行了处理。如果对正逆指标归一化采用的方法一样,为了体现逆指标的不利影响,最后应该总分减去逆指标的得分的。两种方法不同,但都是为了体现逆指标对综合得分的不利影响。

  • 代码如下,原代码在Jupyter Notebook执行
#导入数据
import pandas as pd
import pymysql
import numpy as np

def conn_sql():
    conn = pymysql.connect(
    						#具体数据库信息涉及隐私 删去
                        )
    sql_cmd = "SELECT * FROM commission_channel_info_08"
    data = pd.read_sql(sql_cmd, conn)
    return data
    
data = conn_sql()


#处理缺失值
data.loc[data.org_channel_type == '直销渠道', 'star_level'] = '7'
data.loc[data.star_level == '', 'star_level'] = np.NaN

data['star_level'] = data['star_level'].fillna(method='ffill')
data['star_level'] = data['star_level'].astype('int')


#对部分字段做log变换
indexList=['keep_card_user', 'dmrn_mark',
           'lowfee_user', 'month_off_user','old_user_num','batch_open_num', 'err_time_busi', 'open_acct_num','org_user_numm',
           'dkm_busi_ratio', 'same_money_ratio', 'recount_user', 'recount_fee', 'zd_yw_jc_ratio', 'zd_yw_lc_ratio']

for index in indexList:
    print('======================'+index+'==========================') 
    print(data[index].skew())
    data[index] = np.log(data[index] + 1e-5) 
    print(data[index].skew())

#标准化处理
data.set_index('object_id', inplace=True)

dataPos = data[['star_level', 'innet_user', 'org_user_numm']]

dataNeg = data[['sum_money_ratio', 'arpu_ratio','keep_card_user', 'dmrn_mark', 'nonefee_user', 'lowfee_user', 
                'month_off_user','old_user_num', 'batch_open_num', 'err_time_busi', 'open_acct_num', 'dkm_hb',
                'dkm_busi_ratio', 'same_money','same_money_ratio', 'recount_flag', 'recount_user', 'recount_fee', 
                'zd_yw_jc', 'zd_yw_jc_ratio', 'zd_yw_lc',  'zd_yw_lc_ratio']]


# 正向指标
dataPos = (dataPos - dataPos.min())/(dataPos.max() - dataPos.min())

# 负向指标
dataNeg = (dataNeg.max() - dataNeg)/(dataNeg.max() - dataNeg.min())
    
df = pd.merge(dataPos, dataNeg, how='inner', left_index = True, right_index=True)
df.to_csv("dfStandard.csv", header=True, encoding="gbk")

# 求k
import math

df2 = df
rows = df2.index.size  # 行
cols = df2.columns.size  # 列
k = 1.0 / math.log(rows)


df3 = df2

for index, row in df2.iteritems():
    indexSum = df3[index].sum()
    for i in range(0,len(row)): 
        if df3[index][i] == 0:
            lnfij2 = 0.0
        else:
            p2 = df3[index][i] / indexSum
            lnfij2 = math.log(p2) * p2 * (-k)
#             lnfij2 = p.apply(lambda x: math.log(x) * x * (-k))
        df3[index][i] = lnfij2
        
# 计算冗余度
E = df3
d = 1 - E.sum(axis=0)


#最后通过标准化之后的值,计算得分,该部分涉及业务逻辑,未上传
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值