注:参考多篇文章与代码所得,可能在某些过程处存在理解错误,请大家批评指正。
一、实验背景
国际援助是国际人道主义非政府组织(NGO),它致力于消除贫困,并在发生灾害时为经济落后国家提供基本设施和救济。
目前,国际援助组织已筹集约1000万美元。现在,NGO的CEO需要决定如何策略性地和有效地使用这笔资金。因此,首席执行官必须决定选择最迫切需要援助的国家。因此,您作为数据科学家的工作是利用一些社会经济和健康因素对国家进行归类,以确定国家的整体发展水平,据此建议首席执行官需要最关注的国家。
二、实验内容
利用社会经济和健康因素对国家整体发展水平进行聚类分析,以为国家援助提供参考信息。
三、实验步骤
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#一、数据导入
data = pd.read_csv("D:/班级作业/数据挖掘/实验报告/实验三 对国家聚类以用于国际精准援助/Country-data.csv")
data.set_index("country",inplace=True)
data.head()
#二、数据探索性分析
# 1.查看数据规模
print (data.shape)
# 2.粗略查看数据集
print (data.describe())
# 3.查看缺失情况(发现无缺失)
print (data.isnull().sum())
# 4.直方图查看各特征的分布
data.hist(figsize=(15,10))
plt.show()
# 5.箱线图查看数据分布,可以发现,国家之间贫富差距很大
data.boxplot(figsize=(15,10))
plt.show()
#三、特征预处理
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
plt.rcParams['axes.unicode_minus'] = False # 显示负号
# 1.斯皮尔曼相关性分析可视化: 特征间相关系数(-1~1之间,1为强正相关,-1为强负相关)
corr = data.corr(method="spearman")
plt.figure(figsize=(10,10))
sns.heatmap(corr,annot=True)
plt.show()
# 2.皮尔逊相关性分析可视化
corr = data.corr(method="pearson")
plt.figure(figsize=(10,10))
sns.heatmap(corr,annot=True)
plt.show()
#3.构造两个新的特征值:健康指数(h_s)和经济指数(e_s)
import math
from numpy import array
# 第一列是负向指标,先正向化处理
data.iloc[:,0:1] = np.max(data.iloc[:,0:1])-data.iloc[:,0:1]
#定义熵权法函数
def cal_weight(x):
# 无量纲化
df = x.apply(lambda x: ((x - np.min(x)) / (np.max(x) - np.min(x))))
# 求k
rows = x.index.size # 行
cols = x.columns.size # 列
k = 1.0 / math.log(rows)
lnf = [[None] * cols for i in range(rows)]
# 矩阵计算
# 信息熵
x = array(x)
lnf = [[None] * cols for i in range(rows)]
lnf = array(lnf)
for i in range(0, rows):
for j in range(0, cols):
if x[i][j] <= 0:
lnfij = 0.0
else:
p = x[i][j] / x.sum(axis=0)[j]
#print(x[i][j])
lnfij = math.log(p) * p * (-k)
lnf[i][j] = lnfij
lnf = pd.DataFrame(lnf)
E = lnf
# 计算冗余度
d = 1 - E.sum(axis=0)
# 计算各指标的权重
w = [[None] * 1 for i in range(cols)]
for j in range(0, cols):
wj = d[j] / sum(d)
w[j] = wj
# 计算各样本的综合得分,用最原始的数据
w = pd.DataFrame(w)
return w
weight1 = cal_weight(data.iloc[:,0:4])
weight1.index = data.iloc[:,0:4].columns
weight1.columns = ['weight']
print("“健康”角度熵权法求得的权值为:")
print(weight1)
weight2 = cal_weight(data.iloc[:,4:])
weight2.index = data.iloc[:,4:].columns
weight2.columns = ['weight']
print("“经济”角度熵权法求得的权值为:")
print(weight2)
data = (data-data.min())/(data.max()-data.min())
data["h_s"]=0.206*data["child_mort"]+0.33*data["health"]+0.162*data["life_expec"]+0.302*data["total_fer"]
data["e_s"]=0.1616*data["exports"]+0.1488*data["imports"]+0.296*data["income"]+0.2496*data["inflation"]+0.342*data["gdpp"]
#data.to_csv("")
data
#4.初步查看数据分布
import matplotlib.pyplot as plt
#matplotlib设置默认字体
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.xlabel('健康水平')
plt.ylabel('经济水平')
plt.scatter(data["h_s"], data["e_s"], alpha=0.5)
data = data[["h_s","e_s"]]
data
plt.show()
#四、建模分析
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture as GMM
from sklearn.metrics import silhouette_samples, silhouette_score
import matplotlib.cm as cm
#1.基于silhouette系数确定平均silhouette得分
X = np.array(data)
range_n_clusters = [i for i in range(2,12)]
for n_clusters in range_n_clusters:
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.set_size_inches(18, 7)
ax1.set_xlim([-0.1, 1])
ax1.set_ylim([0, len(X) + (n_clusters + 1) * 10])
clusterer = GMM(n_components=n_clusters, random_state=42)
cluster_labels = clusterer.fit_predict(X)
silhouette_avg = silhouette_score(X, cluster_labels)
print(
"For n_clusters =",
n_clusters,
"The average silhouette_score is :",
silhouette_avg,
)
sample_silhouette_values = silhouette_samples(X, cluster_labels)
#2、导出轮廓图与可视化图
y_lower = 10
for i in range(n_clusters):
ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
ith_cluster_silhouette_values.sort()
size_cluster_i = ith_cluster_silhouette_values.shape[0]
y_upper = y_lower + size_cluster_i
color = cm.nipy_spectral(float(i) / n_clusters)
ax1.fill_betweenx(
np.arange(y_lower, y_upper),
0,
ith_cluster_silhouette_values,
facecolor=color,
edgecolor=color,
alpha=0.7,
)
ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
y_lower = y_upper + 10
ax1.set_title("各种集群的轮廓图")
ax1.set_xlabel("轮廓系数值")
ax1.set_ylabel("簇标签")
ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
ax1.set_yticks([])
ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])
colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
ax2.scatter(
X[:, 0], X[:, 1], marker=".", s=30, lw=0, alpha=0.7, c=colors, edgecolor="k"
)
centers = clusterer.means_
ax2.scatter(
centers[:, 0],
centers[:, 1],
marker="o",
c="white",
alpha=1,
s=200,
edgecolor="k",
)
for i, c in enumerate(centers):
ax2.scatter(c[0], c[1], marker="$%d$" % i, alpha=1, s=50, edgecolor="k")
ax2.set_title("集群数据的可视化")
ax2.set_xlabel("第一个特征的特征空间")
ax2.set_ylabel("第二个特征的特征空间")
plt.suptitle(
"Silhouette analysis for KMeans clustering on sample data with n_clusters = %d"
% n_clusters,
fontsize=14,
fontweight="bold",
)
plt.savefig('silhouette_score_%d.png' % n_clusters)
plt.show()
# 3、结果的可视化函数
from matplotlib.patches import Ellipse
def draw_ellipse(position, covariance, ax=None, **kwargs):
ax = ax or plt.gca()
# Convert covariance to principal axes
if covariance.shape == (2, 2):
U, s, Vt = np.linalg.svd(covariance)
angle = np.degrees(np.arctan2(U[1, 0], U[0, 0]))
width, height = 2 * np.sqrt(s)
else:
angle = 0
width, height = 2 * np.sqrt(covariance)
# Draw the Ellipse
for nsig in range(1, 4):
ax.add_patch(Ellipse(position, nsig * width, nsig * height,
angle, **kwargs))
#绘制结果图,将会调用上方的函数
def plot_gmm(gmm, x, label=True, ax=None):
ax = ax or plt.gca()
labels = gmm.fit(x).predict(x)
if label:
ax.scatter(x[:, 0], x[:, 1], c=labels, s=40, cmap='viridis', zorder=2)
else:
ax.scatter(x[:, 0], x[:, 1], s=40, zorder=2)
ax.axis('equal')
w_factor = 0.2 / gmm.weights_.max()
for pos, covariance, weight in zip(gmm.means_, gmm.covariances_, gmm.weights_):
draw_ellipse(pos, covariance, alpha=weight * w_factor) #调用上方的函数,得到最终的可视化结果
gmm = GMM(n_components=7, random_state=42)
plot_gmm(gmm, X) # 自定义结果可视化函数
pd.set_option('display.max_rows',200)
data["final"] = gmm.predict(X)
data.to_csv("聚类结果.csv") #导出最终结果
data
plt.show()
1.数据导入
2.数据探索性分析
1)查看数据规模、数据集、缺失情况等
2)直方图查看各特征的分布
3)箱线图查看数据分布
3.特征预处理
1)斯皮尔曼相关性分析可视化与皮尔逊相关性分析可视化
2)构造两个新的特征值:健康指数(h_s)和经济指数(e_s)
3)初步查看数据分布
4.建模分析(使用GMM聚类方法)
1)基于silhouette系数确定平均silhouette得分
2) 导出轮廓图与可视化图
注:从n_cluster=2至n_cluster=11,选择了部分截图
3)导出聚类结果(指定最佳类别个数为7)
四、实验结果与结论
在数据探索性分析中,先查看了数据规模、缺失情况(发现无缺失);后使用直方图查看了各特征的分布,用箱线图查看了数据分布,从中发现,不同国家之间的贫富差距是很大的。
在特征预处理中,首先使用斯皮尔曼相关性分析可视化与皮尔逊相关性分析可视化,得到两幅热力图;后使用主客观赋权相结合,加权构造了健康指数(h_s)和经济指数(e_s)两个新特征;最后初步查看健康指数和经济指数的数据分布。
在建模分析中,使用GMM聚类方法对这两个特征进行聚类分析,指定分为7类,得到最终聚类结果。