引言:熵值法的基本概念与理论基础
熵值法(Entropy Method)是一种基于信息熵理论的客观赋权方法,由香农(C.E. Shannon)在信息论中引入。在多指标综合评价中,熵值法通过分析各指标数据的离散程度来确定权重,离散程度越大,该指标提供的信息量越多,权重就越大。这种方法避免了主观赋权的偏差,具有较强的数学严谨性和客观性。
熵值法的核心思想是:如果某个指标在所有样本中的取值差异很小(即数据离散程度低),说明该指标在综合评价中发挥的作用较小,应赋予较低的权重;反之,如果取值差异很大,则应赋予较高权重。这种方法特别适用于指标间存在相关性、且需要客观赋权的复杂系统评价问题。
熵值法的基本原理
信息熵的概念
信息熵是度量系统不确定性的一个物理量。对于一个离散随机变量X,其概率分布为P(X) = {p₁, p₂, …, pₙ},则信息熵定义为:
H(X) = -Σ(pᵢ * ln(pᵢ))
其中,pᵢ表示事件i发生的概率,ln是自然对数。信息熵越大,系统的不确定性越高,包含的信息量越少;信息熵越小,系统的确定性越高,包含的信息量越多。
熵值法在综合评价中的应用
在综合评价中,假设有m个评价对象,n个评价指标,形成原始数据矩阵X = (xᵢⱼ)ₘₓₙ。熵值法通过以下步骤计算各指标的权重:
- 数据标准化:消除量纲影响,使不同指标具有可比性
- 计算比重:计算每个样本在各指标中的比重
- 计算熵值:根据比重计算各指标的信息熵
- 计算权重:根据熵值计算各指标的权重系数
熵值法的详细计算步骤
第一步:数据标准化处理
由于不同指标的量纲和数量级可能不同,首先需要对原始数据进行标准化处理。常见的标准化方法有极差法、Z-score法等。这里介绍最常用的极差标准化方法:
对于效益型指标(越大越好):
yᵢⱼ = (xᵢⱼ - min(xⱼ)) / (max(xⱼ) - min(xⱼ))
对于成本型指标(越小越好):
yᵢⱼ = (max(xⱼ) - xᵢⱼ) / (max(xⱼ) - 3. 第二步:计算指标比重
计算第j项指标下第i个样本占该指标的比重:
pᵢⱼ = yᵢⱼ / Σ(yᵢⱼ) (i=1,2,…,m; j=1,2,…,n)
### 第三步:计算信息熵
计算第j项指标的信息熵:
eⱼ = -k * Σ(pᵢⱼ * ln(pᵢⱼ))
其中k为常数,通常取k = 1/ln(m),以确保eⱼ ∈ [0,1]。
### 第四步:计算信息冗余度
信息冗余度(也称为差异系数)反映了指标提供信息的能力:
dⱼ = 1 - eⱼ
### 第五步:计算指标权重
最终计算各指标的权重:
wⱼ = dⱼ / Σ(dⱼ)
## Python代码实现
下面是一个完整的Python实现,包含详细的注释和示例数据:
```python
import numpy as np
import pandas as
# 示例数据:假设我们有5个地区,每个地区有4个评价指标
# 指标1:GDP增长率(效益型)
# 指标2:人均收入(效益型)
# 挑选:失业率(成本型)
# 指标4:教育投入占比(效益型)
data = {
'地区': ['A', 'B', 'C', 'D', 'E'],
'GDP增长率': [8.2, 7.5, 6.8, 7.2, 8.5],
'人均收入': [50000, 48000, 42000, 45000, 52000],
'失业率': [3.2, 3.8, 4.5, 4.0, 3.0],
'教育投入占比': [4.2, 3.8, 3.5, 4.0, 4.5]
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)
print("\n" + "="*50 + "\n")
# 提取数值数据(排除地区列)
numeric_data = df.iloc[:, 1:].values
m, n = numeric_data.shape
# 定义指标类型:True表示效益型,False表示成本型
benefit_type = [True, True, False, True]
# 第一步:数据标准化
def standardize(data, benefit_type):
"""
数据标准化处理
data: 原始数据矩阵
benefit_type: 指标类型列表,True为效益型,False为成本型
"""
standardized = np.zeros_like(data)
for j in range(data.shape[1]):
col = data[:, j]
if benefit_type[j]:
# 效益型指标:越大越好
standardized[:, j] = (col - col.min()) / (col.max() - col.min())
else:
# 成本型指标:越小越好
standardized[:, j] = (col.max() - col) / (col.max() - col.min())
return standardized
# 执行标准化
y = standardize(numeric_data, benefit_type)
print("标准化后的数据:")
print(y)
print("\n" + "="*50 + "\n")
# 第二步:计算指标比重
def calculate_proportion(y):
"""
计算指标比重
"""
# 避免0值导致对数计算错误,添加一个极小值
epsilon = 1e-10
p = y + epsilon
# 计算每列的和
col_sums = p.sum(axis=0)
# 计算比重
p = p / col_sums
return p
p = calculate_proportion(y)
print("指标比重:")
print(p)
print("\n" + "="*50 + "\n")
# 第三步:计算信息熵
def calculate_entropy(p):
"""
计算信息熵
"""
m = p.shape[0]
k = 1 / np.log(m)
# 计算每列的熵值
e = -k * np.sum(p * np.log(p), axis=0)
return e
e = calculate_entropy(p)
print("各指标的信息熵:")
for j, col_name in enumerate(df.columns[1:]):
print(f"{col_name}: {e[j]:.4f}")
print("\n" + "="*50 + "\n")
# 第四步:计算信息冗余度
def calculate_redundancy(e):
"""
计算信息冗余度(差异系数)
"""
return 1 - e
d = calculate_redundancy(e)
print("各指标的信息冗余度:")
for j, col_name in enumerate(df.columns[1:]):
print(f"{col_name}: {d[j]:.4f}")
print("\n" + "="*50 + "\n")
# 第五步:计算权重
def calculate_weight(d):
"""
计算指标权重
"""
w = d / np.sum(d)
return w
w = calculate_weight(d)
print("各指标的最终权重:")
for j, col_name in enumerate(df.columns[1:]):
print(f"{col_name}: {w[j]:.4f} ({w[j]*100:.2f}%)")
print("\n" + "="*50 + "\n")
# 综合评价得分计算
def calculate_score(y, w):
"""
计算综合评价得分
y: 标准化后的数据
w: 权重向量
"""
return np.dot(y, w)
scores = calculate_score(y, w)
print("各地区的综合评价得分:")
for i, region in enumerate(df['地区']):
print(f"{region}: {scores[i]:.4f}")
# 结果排序
sorted_indices = np.argsort(scores)[::-1] # 降序排列
print("\n综合评价排名:")
for rank, idx in enumerate(sorted_indices, 1):
print(f"第{rank}名: {df['地区'][idx]} (得分: {scores[idx]:.4f})")
实际应用案例:城市综合实力评价
案例背景
假设我们要评价5个城市的综合实力,选取了以下6个指标:
- GDP总量(效益型):反映经济规模
- 人均GDP(效益型):反映经济效率
- 第三产业占比(效益型):反映产业结构优化程度
- 固定资产投资(效益型):反映发展后劲
- 居民人均可支配收入(效益型):反映民生水平 6.空气质量优良天数(效益型):反映生态环境质量
完整案例代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 创建更复杂的案例数据
np.random.seed(42) # 保证结果可复现
cities = ['北京', '上海', '广州', '深圳', '杭州']
data = {
'城市': cities,
'GDP总量(万亿)': [3.61, 3.87, 2.50, 2.69, 1.61],
'人均GDP(万元)': [17.4, 16.8, 15.0, 15.8, 13.5],
'第三产业占比(%)': [82.5, 72.7, 70.6, 60.1, 64.2],
'固定资产投资(万亿)': [0.79, 0.76, 0.58, 0.52, 0.57],
'居民人均可支配收入(万元)': [7.5, 7.2, 6.8, 6.4, 6.0],
'空气质量优良天数': [288, 265, 295, 310, 285]
}
df = pd.DataFrame(data)
print("城市综合实力评价原始数据:")
print(df)
print("\n" + "="*60 + "\n")
# 提取数值数据
numeric_data = df.iloc[:, 1:].values
m, n = numeric_data.shape
# 所有指标都是效益型
benefit_type = [True] * n
# 封装完整的熵值法计算过程
class EntropyMethod:
def __init__(self, benefit_type):
self.benefit_type = benefit_type
self.weights = None
self.standardized_data = None
self.entropy = None
self.redundancy = None
def fit(self, data):
"""
执行完整的熵值法计算
"""
# 1. 数据标准化
self.standardized_data = self._standardize(data)
# 2. 计算比重
p = self._calculate_proportion(self.standardized_data)
# 3. 计算信息熵
self.entropy = self._calculate_entropy(p)
# 4. 计算信息冗余度
self.redundancy = self._calculate_redundancy(self.entropy)
# 5. 计算权重
self.weights = self._calculate_weight(self.redundancy)
return self
def _standardize(self, data):
"""数据标准化"""
standardized = np.zeros_like(data)
for j in range(data.shape[1]):
col = data[:, j]
if self.benefit_type[j]:
standardized[:, j] = (col - col.min()) / (col.max() - col.min())
else:
standardized[:, j] = (col.max() - col) / (col.max() - col.min())
return standardized
def _calculate_proportion(self, y):
"""计算指标比重"""
epsilon = 1e-10
p = y + epsilon
col_sums = p.sum(axis=0)
return p / col_sums
def _calculate_entropy(self, p):
"""计算信息熵"""
m = p.shape[0]
k = 1 / np.log(m)
return -k * np.sum(p * np.log(p), axis=0)
def _calculate_redundancy(self, e):
"""计算信息冗余度"""
return 1 - e
def _calculate_weight(self, d):
"""计算权重"""
return d / np.sum(d)
def predict(self, data):
"""计算综合得分"""
standardized = self._standardize(data)
return np.dot(standardized, self.weights)
# 实例化并计算
entropy_method = EntropyMethod(benefit_type)
entropy_method.fit(numeric_data)
# 输出详细结果
print("=== 熵值法计算结果 ===\n")
print("1. 标准化后的数据:")
std_df = pd.DataFrame(
entropy_method.standardized_data,
columns=df.columns[1:],
index=df['城市']
)
print(std_df.round(4))
print("\n" + "-"*60 + "\n")
print("2. 各指标信息熵:")
for i, col in enumerate(df.columns[1:]):
print(f" {col}: {entropy_method.entropy[i]:.6f}")
print("\n" + "-"*60 + "\n")
print("3. 各指标信息冗余度:")
for i, col in enumerate(df.columns[1:]):
print(f" {col}: {entropy_method.redundancy[i]:.6f}")
print("\n" + "-"*60 + "\n")
print("4. 各指标权重:")
weights_df = pd.DataFrame({
'指标': df.columns[1:],
'权重': entropy_method.weights,
'权重(%)': entropy_method.weights * 100
})
print(weights_df.round(4))
print("\n" + "-"*60 + "\n")
# 计算综合得分
scores = entropy_method.predict(numeric_data)
print("5. 各城市综合得分及排名:")
results_df = pd.DataFrame({
'城市': df['城市'],
'综合得分': scores
})
results_df['排名'] = results_df['综合得分'].rank(ascending=False, method='min')
results_df = results_df.sort_values('综合得分', ascending=False)
print(results_df.round(4))
print("\n" + "="*60 + "\n")
# 可视化分析
plt.figure(figsize=(14, 6))
# 子图1:权重分布
plt.subplot(1, 2, 1)
bars = plt.barh(range(len(entropy_method.weights)), entropy_method.weights)
plt.yticks(range(len(entropy_method.weights)), df.columns[1:], fontsize=10)
plt.xlabel('权重', fontsize=12)
plt.title('各指标权重分布', fontsize=14, fontweight='bold')
for i, bar in enumerate(bars):
width = bar.get_width()
plt.text(width + 0.001, bar.get_y() + bar.get_height()/2,
f'{width:.4f}', ha='left', va='center', fontsize=10)
# 子图2:城市综合得分
plt.subplot(1, 2, 2)
colors = plt.cm.viridis(np.linspace(0, 1, len(results_df)))
bars = plt.bar(results_df['城市'], results_df['综合得分'], color=colors)
plt.ylabel('综合得分', fontsize=12)
plt.title('城市综合实力排名', fontsize=14, fontweight='bold')
plt.xticks(rotation=45)
for bar in bars:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width()/2., height + 0.01,
f'{height:.3f}', ha='center', va='bottom', fontsize=10)
plt.tight_layout()
plt.show()
# 敏感性分析:观察权重稳定性
print("\n=== 敏感性分析 ===\n")
print("通过调整数据观察权重变化:")
# 创建一个扰动数据集
np.random.seed(123)
perturbation = np.random.normal(1.0, 0.05, numeric_data.shape) # 5%的随机扰动
perturbed_data = numeric_data * perturbation
entropy_perturbed = EntropyMethod(benefit_type)
entropy_perturbed.fit(perturbed_data)
print("\n原始权重 vs 扰动后权重:")
comparison_df = pd.DataFrame({
'指标': df.columns[1:],
'原始权重': entropy_method.weights,
'扰动后权重': entropy_perturbed.weights,
'变化率(%)': (entropy_perturbed.weights - entropy_method.weights) / entropy_method.weights * 100
})
print(comparison_df.round(4))
熵值法的优缺点分析
优点
- 客观性强:完全基于数据本身的离散程度确定权重,避免了主观判断的偏差
- 数学严谨:有坚实的理论基础,计算过程标准化
- 适用范围广:适用于各种类型的多指标综合评价问题
- 可解释性好:权重大小直接反映指标信息量的多少
缺点
- 对极端值敏感:个别极端值会显著影响权重计算
- 要求样本量适中:样本量过少时,计算结果可能不稳定
- 无法反映指标重要性差异:完全依赖数据,可能忽略实际业务中指标的重要性差异
- 可能产生权重分配不均:当某些指标数据离散度特别大时,可能产生权重过度集中
实际应用中的注意事项
1. 数据预处理
- 异常值处理:在计算前应识别和处理异常值
- 缺失值填补:合理处理缺失数据,避免影响计算结果
- 数据一致性:确保所有指标方向一致(效益型或成本型)
2. 样本量要求
- 一般建议样本量m ≥ 5,否则计算结果可能不稳定
- 指标数量n不宜过多,避免权重过于分散
3. 结果解释
- 权重仅反映数据离散程度,不一定代表实际重要性
- 建议结合主观赋权法(如AHP)进行组合赋权
4. 模型验证
- 通过敏感性分析检验结果的稳定性
- 与其他赋权方法结果进行对比验证
扩展应用:与其他方法的结合
1. 熵值法与AHP结合(组合赋权)
def combined_weight(entropy_weight, ahp_weight, alpha=0.5):
"""
组合赋权:alpha表示熵值法权重占比
"""
return alpha * entropy_weight + (1 - alpha) * ahp_weight
# 示例:假设AHP权重为[0.2, 0.2, 0.2, 0.2, 0.1, 0.1]
ahp_weights = np.array([0.2, 0.2, 0.2, 0.2, 0.1, 0.1])
combined = combined_weight(entropy_method.weights, ahp_weights, alpha=0.6)
print("\n组合权重(熵值法60% + AHP40%):")
for i, col in enumerate(df.columns[1:]):
print(f" {col}: {combined[i]:.4f} ({combined[i]*100:.2f}%)")
2. 熵值法与TOPSIS结合
def topsis_with_entropy(data, benefit_type, entropy_method):
"""
熵值法赋权 + TOPSIS评价
"""
# 1. 标准化
std_data = entropy_method._standardize(data)
# 2. 加权标准化矩阵
weights = entropy_method.weights
weighted_std = std_data * weights
# 3. 确定正理想解和负理想解
# 效益型指标:越大越好;成本型指标:越小越好
ideal_positive = np.array([std_data[:, j].max() if benefit_type[j] else std_data[:, j].min()
for j in range(len(benefit_type))])
ideal_negative = np.array([std_data[:, j].min() if benefit_type[j] else std_data[:, j].max()
for j in range(len(benefit_type))])
# 4. 计算距离
d_positive = np.sqrt(np.sum((weighted_std - ideal_positive * weights)**2, axis=1))
d_negative = np.sqrt(np.sum((weighted_std - ideal_negative * weights)**2, axis=1))
# 5. 计算贴近度
closeness = d_negative / (d_positive + d_negative)
return closeness
# 应用示例
topsis_scores = topsis_with_entropy(numeric_data, benefit_type, entropy_method)
print("\n熵值法+TOPSIS综合得分:")
for i, city in enumerate(df['城市']):
print(f" {city}: {topsis_scores[i]:.4f}")
结论
熵值法作为一种客观赋权方法,在多指标综合评价中具有重要价值。通过分析数据本身的离散程度来确定权重,避免了主观偏差,使评价结果更加科学合理。然而,在实际应用中,我们需要注意其局限性,结合具体问题特点,必要时与其他方法组合使用,以获得更可靠的评价结果。
关键要点总结:
- 客观性:权重完全由数据决定,避免主观干扰
- 适用性:适用于样本量充足、指标间相关性不强的情况
- 局限性:对极端值敏感,可能忽略指标实际重要性差异
- 改进方向:可与主观赋权法、其他评价方法结合使用
通过本文的详细解析和完整代码示例,读者可以掌握熵值法的核心原理、计算步骤和实际应用技巧,为相关研究和实践提供有力工具。# 基于熵值法的综合研究指数值计算方法与实际应用解析
引言:熵值法的基本概念与理论基础
熵值法(Entropy Method)是一种基于信息熵理论的客观赋权方法,由香农(C.E. Shannon)在信息论中引入。在多指标综合评价中,熵值法通过分析各指标数据的离散程度来确定权重,离散程度越大,该指标提供的信息量越多,权重就越大。这种方法避免了主观赋权的偏差,具有较强的数学严谨性和客观性。
熵值法的核心思想是:如果某个指标在所有样本中的取值差异很小(即数据离散程度低),说明该指标在综合评价中发挥的作用较小,应赋予较低的权重;反之,如果取值差异很大,则应赋予较高权重。这种方法特别适用于指标间存在相关性、且需要客观赋权的复杂系统评价问题。
熵值法的基本原理
信息熵的概念
信息熵是度量系统不确定性的一个物理量。对于一个离散随机变量X,其概率分布为P(X) = {p₁, p₂, …, pₙ},则信息熵定义为:
H(X) = -Σ(pᵢ * ln(pᵢ))
其中,pᵢ表示事件i发生的概率,ln是自然对数。信息熵越大,系统的不确定性越高,包含的信息量越少;信息熵越小,系统的确定性越高,包含的信息量越多。
熵值法在综合评价中的应用
在综合评价中,假设有m个评价对象,n个评价指标,形成原始数据矩阵X = (xᵢⱼ)ₘₓₙ。熵值法通过以下步骤计算各指标的权重:
- 数据标准化:消除量纲影响,使不同指标具有可比性
- 计算比重:计算每个样本在各指标中的比重
- 计算熵值:根据比重计算各指标的信息熵
- 计算权重:根据熵值计算各指标的权重系数
熵值法的详细计算步骤
第一步:数据标准化处理
由于不同指标的量纲和数量级可能不同,首先需要对原始数据进行标准化处理。常见的标准化方法有极差法、Z-score法等。这里介绍最常用的极差标准化方法:
对于效益型指标(越大越好):
yᵢⱼ = (xᵢⱼ - min(xⱼ)) / (max(xⱼ) - min(xⱼ))
对于成本型指标(越小越好):
yᵢⱼ = (max(xⱼ) - xᵢⱼ) / (max(xⱼ) - min(xⱼ))
第二步:计算指标比重
计算第j项指标下第i个样本占该指标的比重:
pᵢⱼ = yᵢⱼ / Σ(yᵢⱼ) (i=1,2,...,m; j=1,2,...,n)
第三步:计算信息熵
计算第j项指标的信息熵:
eⱼ = -k * Σ(pᵢⱼ * ln(pᵢⱼ))
其中k为常数,通常取k = 1/ln(m),以确保eⱼ ∈ [0,1]。
第四步:计算信息冗余度
信息冗余度(也称为差异系数)反映了指标提供信息的能力:
dⱼ = 1 - eⱼ
第五步:计算指标权重
最终计算各指标的权重:
wⱼ = dⱼ / Σ(dⱼ)
Python代码实现
下面是一个完整的Python实现,包含详细的注释和示例数据:
import numpy as np
import pandas as pd
# 示例数据:假设我们有5个地区,每个地区有4个评价指标
# 指标1:GDP增长率(效益型)
# 指标2:人均收入(效益型)
# 挑选:失业率(成本型)
# 指标4:教育投入占比(效益型)
data = {
'地区': ['A', 'B', 'C', 'D', 'E'],
'GDP增长率': [8.2, 7.5, 6.8, 7.2, 8.5],
'人均收入': [50000, 48000, 42000, 45000, 52000],
'失业率': [3.2, 3.8, 4.5, 4.0, 3.0],
'教育投入占比': [4.2, 3.8, 3.5, 4.0, 4.5]
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)
print("\n" + "="*50 + "\n")
# 提取数值数据(排除地区列)
numeric_data = df.iloc[:, 1:].values
m, n = numeric_data.shape
# 定义指标类型:True表示效益型,False表示成本型
benefit_type = [True, True, False, True]
# 第一步:数据标准化
def standardize(data, benefit_type):
"""
数据标准化处理
data: 原始数据矩阵
benefit_type: 指标类型列表,True为效益型,False为成本型
"""
standardized = np.zeros_like(data)
for j in range(data.shape[1]):
col = data[:, j]
if benefit_type[j]:
# 效益型指标:越大越好
standardized[:, j] = (col - col.min()) / (col.max() - col.min())
else:
# 成本型指标:越小越好
standardized[:, j] = (col.max() - col) / (col.max() - col.min())
return standardized
# 执行标准化
y = standardize(numeric_data, benefit_type)
print("标准化后的数据:")
print(y)
print("\n" + "="*50 + "\n")
# 第二步:计算指标比重
def calculate_proportion(y):
"""
计算指标比重
"""
# 避免0值导致对数计算错误,添加一个极小值
epsilon = 1e-10
p = y + epsilon
# 计算每列的和
col_sums = p.sum(axis=0)
# 计算比重
p = p / col_sums
return p
p = calculate_proportion(y)
print("指标比重:")
print(p)
print("\n" + "="*50 + "\n")
# 第三步:计算信息熵
def calculate_entropy(p):
"""
计算信息熵
"""
m = p.shape[0]
k = 1 / np.log(m)
# 计算每列的熵值
e = -k * np.sum(p * np.log(p), axis=0)
return e
e = calculate_entropy(p)
print("各指标的信息熵:")
for j, col_name in enumerate(df.columns[1:]):
print(f"{col_name}: {e[j]:.4f}")
print("\n" + "="*50 + "\n")
# 第四步:计算信息冗余度
def calculate_redundancy(e):
"""
计算信息冗余度(差异系数)
"""
return 1 - e
d = calculate_redundancy(e)
print("各指标的信息冗余度:")
for j, col_name in enumerate(df.columns[1:]):
print(f"{col_name}: {d[j]:.4f}")
print("\n" + "="*50 + "\n")
# 第五步:计算权重
def calculate_weight(d):
"""
计算指标权重
"""
w = d / np.sum(d)
return w
w = calculate_weight(d)
print("各指标的最终权重:")
for j, col_name in enumerate(df.columns[1:]):
print(f"{col_name}: {w[j]:.4f} ({w[j]*100:.2f}%)")
print("\n" + "="*50 + "\n")
# 综合评价得分计算
def calculate_score(y, w):
"""
计算综合评价得分
y: 标准化后的数据
w: 权重向量
"""
return np.dot(y, w)
scores = calculate_score(y, w)
print("各地区的综合评价得分:")
for i, region in enumerate(df['地区']):
print(f"{region}: {scores[i]:.4f}")
# 结果排序
sorted_indices = np.argsort(scores)[::-1] # 降序排列
print("\n综合评价排名:")
for rank, idx in enumerate(sorted_indices, 1):
print(f"第{rank}名: {df['地区'][idx]} (得分: {scores[idx]:.4f})")
实际应用案例:城市综合实力评价
案例背景
假设我们要评价5个城市的综合实力,选取了以下6个指标:
- GDP总量(效益型):反映经济规模
- 人均GDP(效益型):反映经济效率
- 第三产业占比(效益型):反映产业结构优化程度
- 固定资产投资(效益型):反映发展后劲
- 居民人均可支配收入(效益型):反映民生水平
- 空气质量优良天数(效益型):反映生态环境质量
完整案例代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 创建更复杂的案例数据
np.random.seed(42) # 保证结果可复现
cities = ['北京', '上海', '广州', '深圳', '杭州']
data = {
'城市': cities,
'GDP总量(万亿)': [3.61, 3.87, 2.50, 2.69, 1.61],
'人均GDP(万元)': [17.4, 16.8, 15.0, 15.8, 13.5],
'第三产业占比(%)': [82.5, 72.7, 70.6, 60.1, 64.2],
'固定资产投资(万亿)': [0.79, 0.76, 0.58, 0.52, 0.57],
'居民人均可支配收入(万元)': [7.5, 7.2, 6.8, 6.4, 6.0],
'空气质量优良天数': [288, 265, 295, 310, 285]
}
df = pd.DataFrame(data)
print("城市综合实力评价原始数据:")
print(df)
print("\n" + "="*60 + "\n")
# 提取数值数据
numeric_data = df.iloc[:, 1:].values
m, n = numeric_data.shape
# 所有指标都是效益型
benefit_type = [True] * n
# 封装完整的熵值法计算过程
class EntropyMethod:
def __init__(self, benefit_type):
self.benefit_type = benefit_type
self.weights = None
self.standardized_data = None
self.entropy = None
self.redundancy = None
def fit(self, data):
"""
执行完整的熵值法计算
"""
# 1. 数据标准化
self.standardized_data = self._standardize(data)
# 2. 计算比重
p = self._calculate_proportion(self.standardized_data)
# 3. 计算信息熵
self.entropy = self._calculate_entropy(p)
# 4. 计算信息冗余度
self.redundancy = self._calculate_redundancy(self.entropy)
# 5. 计算权重
self.weights = self._calculate_weight(self.redundancy)
return self
def _standardize(self, data):
"""数据标准化"""
standardized = np.zeros_like(data)
for j in range(data.shape[1]):
col = data[:, j]
if self.benefit_type[j]:
standardized[:, j] = (col - col.min()) / (col.max() - col.min())
else:
standardized[:, j] = (col.max() - col) / (col.max() - col.min())
return standardized
def _calculate_proportion(self, y):
"""计算指标比重"""
epsilon = 1e-10
p = y + epsilon
col_sums = p.sum(axis=0)
return p / col_sums
def _calculate_entropy(self, p):
"""计算信息熵"""
m = p.shape[0]
k = 1 / np.log(m)
return -k * np.sum(p * np.log(p), axis=0)
def _calculate_redundancy(self, e):
"""计算信息冗余度"""
return 1 - e
def _calculate_weight(self, d):
"""计算权重"""
return d / np.sum(d)
def predict(self, data):
"""计算综合得分"""
standardized = self._standardize(data)
return np.dot(standardized, self.weights)
# 实例化并计算
entropy_method = EntropyMethod(benefit_type)
entropy_method.fit(numeric_data)
# 输出详细结果
print("=== 熵值法计算结果 ===\n")
print("1. 标准化后的数据:")
std_df = pd.DataFrame(
entropy_method.standardized_data,
columns=df.columns[1:],
index=df['城市']
)
print(std_df.round(4))
print("\n" + "-"*60 + "\n")
print("2. 各指标信息熵:")
for i, col in enumerate(df.columns[1:]):
print(f" {col}: {entropy_method.entropy[i]:.6f}")
print("\n" + "-"*60 + "\n")
print("3. 各指标信息冗余度:")
for i, col in enumerate(df.columns[1:]):
print(f" {col}: {entropy_method.redundancy[i]:.6f}")
print("\n" + "-"*60 + "\n")
print("4. 各指标权重:")
weights_df = pd.DataFrame({
'指标': df.columns[1:],
'权重': entropy_method.weights,
'权重(%)': entropy_method.weights * 100
})
print(weights_df.round(4))
print("\n" + "-"*60 + "\n")
# 计算综合得分
scores = entropy_method.predict(numeric_data)
print("5. 各城市综合得分及排名:")
results_df = pd.DataFrame({
'城市': df['城市'],
'综合得分': scores
})
results_df['排名'] = results_df['综合得分'].rank(ascending=False, method='min')
results_df = results_df.sort_values('综合得分', ascending=False)
print(results_df.round(4))
print("\n" + "="*60 + "\n")
# 可视化分析
plt.figure(figsize=(14, 6))
# 子图1:权重分布
plt.subplot(1, 2, 1)
bars = plt.barh(range(len(entropy_method.weights)), entropy_method.weights)
plt.yticks(range(len(entropy_method.weights)), df.columns[1:], fontsize=10)
plt.xlabel('权重', fontsize=12)
plt.title('各指标权重分布', fontsize=14, fontweight='bold')
for i, bar in enumerate(bars):
width = bar.get_width()
plt.text(width + 0.001, bar.get_y() + bar.get_height()/2,
f'{width:.4f}', ha='left', va='center', fontsize=10)
# 子图2:城市综合得分
plt.subplot(1, 2, 2)
colors = plt.cm.viridis(np.linspace(0, 1, len(results_df)))
bars = plt.bar(results_df['城市'], results_df['综合得分'], color=colors)
plt.ylabel('综合得分', fontsize=12)
plt.title('城市综合实力排名', fontsize=14, fontweight='bold')
plt.xticks(rotation=45)
for bar in bars:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width()/2., height + 0.01,
f'{height:.3f}', ha='center', va='bottom', fontsize=10)
plt.tight_layout()
plt.show()
# 敏感性分析:观察权重稳定性
print("\n=== 敏感性分析 ===\n")
print("通过调整数据观察权重变化:")
# 创建一个扰动数据集
np.random.seed(123)
perturbation = np.random.normal(1.0, 0.05, numeric_data.shape) # 5%的随机扰动
perturbed_data = numeric_data * perturbation
entropy_perturbed = EntropyMethod(benefit_type)
entropy_perturbed.fit(perturbed_data)
print("\n原始权重 vs 扰动后权重:")
comparison_df = pd.DataFrame({
'指标': df.columns[1:],
'原始权重': entropy_method.weights,
'扰动后权重': entropy_perturbed.weights,
'变化率(%)': (entropy_perturbed.weights - entropy_method.weights) / entropy_method.weights * 100
})
print(comparison_df.round(4))
熵值法的优缺点分析
优点
- 客观性强:完全基于数据本身的离散程度确定权重,避免了主观判断的偏差
- 数学严谨:有坚实的理论基础,计算过程标准化
- 适用范围广:适用于各种类型的多指标综合评价问题
- 可解释性好:权重大小直接反映指标信息量的多少
缺点
- 对极端值敏感:个别极端值会显著影响权重计算
- 要求样本量适中:样本量过少时,计算结果可能不稳定
- 无法反映指标重要性差异:完全依赖数据,可能忽略实际业务中指标的重要性差异
- 可能产生权重分配不均:当某些指标数据离散度特别大时,可能产生权重过度集中
实际应用中的注意事项
1. 数据预处理
- 异常值处理:在计算前应识别和处理异常值
- 缺失值填补:合理处理缺失数据,避免影响计算结果
- 数据一致性:确保所有指标方向一致(效益型或成本型)
2. 样本量要求
- 一般建议样本量m ≥ 5,否则计算结果可能不稳定
- 指标数量n不宜过多,避免权重过于分散
3. 结果解释
- 权重仅反映数据离散程度,不一定代表实际重要性
- 建议结合主观赋权法(如AHP)进行组合赋权
4. 模型验证
- 通过敏感性分析检验结果的稳定性
- 与其他赋权方法结果进行对比验证
扩展应用:与其他方法的结合
1. 熵值法与AHP结合(组合赋权)
def combined_weight(entropy_weight, ahp_weight, alpha=0.5):
"""
组合赋权:alpha表示熵值法权重占比
"""
return alpha * entropy_weight + (1 - alpha) * ahp_weight
# 示例:假设AHP权重为[0.2, 0.2, 0.2, 0.2, 0.1, 0.1]
ahp_weights = np.array([0.2, 0.2, 0.2, 0.2, 0.1, 0.1])
combined = combined_weight(entropy_method.weights, ahp_weights, alpha=0.6)
print("\n组合权重(熵值法60% + AHP40%):")
for i, col in enumerate(df.columns[1:]):
print(f" {col}: {combined[i]:.4f} ({combined[i]*100:.2f}%)")
2. 熵值法与TOPSIS结合
def topsis_with_entropy(data, benefit_type, entropy_method):
"""
熵值法赋权 + TOPSIS评价
"""
# 1. 标准化
std_data = entropy_method._standardize(data)
# 2. 加权标准化矩阵
weights = entropy_method.weights
weighted_std = std_data * weights
# 3. 确定正理想解和负理想解
# 效益型指标:越大越好;成本型指标:越小越好
ideal_positive = np.array([std_data[:, j].max() if benefit_type[j] else std_data[:, j].min()
for j in range(len(benefit_type))])
ideal_negative = np.array([std_data[:, j].min() if benefit_type[j] else std_data[:, j].max()
for j in range(len(benefit_type))])
# 4. 计算距离
d_positive = np.sqrt(np.sum((weighted_std - ideal_positive * weights)**2, axis=1))
d_negative = np.sqrt(np.sum((weighted_std - ideal_negative * weights)**2, axis=1))
# 5. 计算贴近度
closeness = d_negative / (d_positive + d_negative)
return closeness
# 应用示例
topsis_scores = topsis_with_entropy(numeric_data, benefit_type, entropy_method)
print("\n熵值法+TOPSIS综合得分:")
for i, city in enumerate(df['城市']):
print(f" {city}: {topsis_scores[i]:.4f}")
结论
熵值法作为一种客观赋权方法,在多指标综合评价中具有重要价值。通过分析数据本身的离散程度来确定权重,避免了主观偏差,使评价结果更加科学合理。然而,在实际应用中,我们需要注意其局限性,结合具体问题特点,必要时与其他方法组合使用,以获得更可靠的评价结果。
关键要点总结:
- 客观性:权重完全由数据决定,避免主观干扰
- 适用性:适用于样本量充足、指标间相关性不强的情况
- 局限性:对极端值敏感,可能忽略指标实际重要性差异
- 改进方向:可与主观赋权法、其他评价方法结合使用
通过本文的详细解析和完整代码示例,读者可以掌握熵值法的核心原理、计算步骤和实际应用技巧,为相关研究和实践提供有力工具。
