一、基本原理
在信息论中,熵是对不确定性的一种度量。信息量越大,不确定性就越小,熵也就越小;信息量越小,不确定性越大,熵也越大。
根据熵的特性,可以通过计算熵值来判断一个事件的随机性及无序程度,也可以用熵值来判断某个指标的离散程度,指标的离散程度越大,该指标对综合评价的影响(权重)越大,其熵值越小。
二、熵值法步骤
-
选取n个国家,m个指标,则
为第i个国家的第j个指标的数值(i=1, 2…, n; j=1,2,…, m); -
指标的归一化处理:异质指标同质化
由于各项指标的计量单位并不统一,因此在用它们计算综合指标前,先要对它们进行标准化处理,即把指标的绝对值转化为相对值,并令
,从而解决各项不同质指标值的同质化问题。而且,由于正向指标和负向指标数值代表的含义不同(正向指标数值越高越好,负向指标数值越低越好),因此,对于高低指标我们用不同的算法进行数据标准化处理。其具体方法如下:
正向指标:
负向指标:
则
为第i个国家的第j个指标的数值(i=1, 2…, n; j=1, 2,…, m)。为了方便起见,归一化后的数据仍记为[图片上传失败…(image-5bd2d6-1545816016204)]
- 计算第j项指标下第i个国家占该指标的比重:
4. 计算第j项指标的熵值:
其中
. 满足
;
- 计算信息熵冗余度:
6. 计算各项指标的权值:
7. 计算各国家的综合得分:
注:对正逆指标归一化的时候如果采用的方法不一样,正指标归一化得到的值会大一些,逆指标的归一化得到的值会小一些,然后算权重,逆指标对应的权重也会相应的小,从而逆指标对应的得分也小些,就相当于对逆指标进行了处理。如果对正逆指标归一化采用的方法一样,为了体现逆指标的不利影响,最后应该总分减去逆指标的得分的。两种方法不同,但都是为了体现逆指标对综合得分的不利影响。
- 代码如下,原代码在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)
#最后通过标准化之后的值,计算得分,该部分涉及业务逻辑,未上传