248 KiB
248 KiB
Лабораторная 5¶
In [47]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
from scipy.cluster.hierarchy import dendrogram, linkage, fcluster
from sklearn.metrics import silhouette_score
df = pd.read_csv(".//csv//EconomicData.csv")
print(df.columns)
print(df.head())
Бизнес-цель: сегментировать страны на основе экономических показателей для определения схожих групп стран и последующего анализа каждой группы.
In [48]:
df = df.copy()
df_clean = df.dropna()
if not np.issubdtype(df_clean.dtypes.iloc[1], np.number):
print("Данные содержат текстовые значения.")
cleaned_data = df_clean.select_dtypes(include=[np.number])
print(f"Исходный размер датасета: {df.shape[0]}")
print(f"Очищенный размер датасета: {df_clean.shape[0]}")
df = pd.get_dummies(df_clean, columns=['country'], drop_first=True)
In [49]:
# Выбор признаков для кластеризации
features = ['index price', 'inflationrate', 'oil prices', 'exchange_rate', 'gdppercent',
'percapitaincome', 'unemploymentrate', 'manufacturingoutput', 'tradebalance', 'USTreasury']
Стандартизируем, чтобы устранить влияние масштаба. А также понизим размерность с помощью РСА для уменьшения количества признаков для визуализации данных.
In [50]:
# Предобработка данных: стандартизация
scaler = StandardScaler()
scaled_data = scaler.fit_transform(df[features])
# Понижение размерности с помощью PCA
pca = PCA(n_components=2)
pca_data = pca.fit_transform(scaled_data)
Используем метод главных компонент (PCA) для уменьшения размерности данных до 2D для визуализации.
In [51]:
# Неиерархическая
kmeans = KMeans(n_clusters=3, random_state=42)
kmeans_labels = kmeans.fit_predict(scaled_data)
# Визуализация кластеров K-Means
plt.figure(figsize=(10, 6))
sns.scatterplot(x=pca_data[:, 0], y=pca_data[:, 1], hue=kmeans_labels, palette='inferno', s=100)
plt.title('K-Means Clustering')
plt.xlabel('Количество кластеров')
plt.ylabel('Инерция')
plt.show()
#оценка неиерархического
silhouette_avg_kmeans = silhouette_score(scaled_data, kmeans_labels)
Для иерархической кластеризации потребуется предварительно определить количество кластеров, так как она не возвращает метки кластеров.
In [52]:
# Иерархическая кластеризация
linked = linkage(scaled_data, 'ward')
# Визуализация
plt.figure(figsize=(10, 7))
dendrogram(linked, orientation='top', distance_sort='descending', show_leaf_counts=True)
plt.title('Иерархическая')
plt.show()
In [53]:
# Определение меток
n_clusters = 3
hierarchical_labels = fcluster(linked, n_clusters, criterion='maxclust')
In [54]:
# Визуализация кластеров
plt.figure(figsize=(10, 6))
sns.scatterplot(x=pca_data[:, 0], y=pca_data[:, 1], hue=hierarchical_labels, palette='inferno', s=100)
plt.title('Иерархическая')
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.show()
In [55]:
# Добавление меток кластеров в исходный датафрейм
df['Cluster'] = kmeans_labels
# Удаление нечисловых столбцов перед вычислением среднего
numeric_columns = df.select_dtypes(include=['float64', 'int64']).columns
cluster_analysis = df.groupby('Cluster')[numeric_columns].mean()
# Вывод результата
print(cluster_analysis)
In [59]:
# Оценка
print(f"Оценка для неиерархического: {round(silhouette_avg_kmeans,5)}")
silhouette_avg = silhouette_score(scaled_data, kmeans_labels)
print(f"Оценка для иерархического: {round(silhouette_avg,5)}")
Оценки совпадают, потому что, вероятно, для расхождения в оценке нужно большее число различных данных.