Кластеризация результатов анкетирования
Автор
In [ ]:
pip install openpyxl
In [ ]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn.cluster import KMeans, AgglomerativeClustering, DBSCAN
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.feature_extraction.text import TfidfVectorizer
from scipy.sparse import hstack
from collections import Counter
# Считываем данные, используя первую строку как заголовки столбцов
df = pd.read_excel('/user/MFB24_1.xlsx')
# Разделяем данные на числовые и текстовые
text_columns = ['3 Какие наиболее ценные знания вы получили на курсе?', '4. Какие знания были наименее ценными?', '10. Что, кроме предметных знаний, было самого ценного на курсе?', '11. Что можно улучшить?'] # Имена столбцов с текстовыми данными
text_data = df[text_columns]
numeric_data = df.drop(columns=text_columns)
# Векторизация текста с помощью TF-IDF для каждого столбца
vectorizers = [TfidfVectorizer() for _ in range(len(text_columns))]
vectorized_texts = [vectorizer.fit_transform(text_data[col]) for col, vectorizer in zip(text_columns, vectorizers)]
# Объединение векторизованных текстовых данных
combined_text = hstack(vectorized_texts).toarray()
# Объединение векторизованных текстовых данных с числовыми данными
combined_data = np.hstack((numeric_data.values, combined_text))
# Стандартизация данных
scaler = StandardScaler(with_mean=False) # Не использовать mean для sparse данных
combined_scaled = scaler.fit_transform(combined_data)
# PCA для выбора наиболее важных признаков
pca = PCA(n_components=3) # Выберем 3 признака для визуализации
pca_data = pca.fit_transform(combined_scaled)
# Анализ вклада признаков в главные компоненты
components = pca.components_
# Определение признаков с наибольшим вкладом в каждую главную компоненту
top_features_pc1 = np.argsort(np.abs(components[0]))[-3:] # Три признака с наибольшим вкладом в первую компоненту
top_features_pc2 = np.argsort(np.abs(components[1]))[-3:] # Три признака с наибольшим вкладом во вторую компоненту
top_features_pc3 = np.argsort(np.abs(components[2]))[-3:] # Три признака с наибольшим вкладом в третью компоненту
# Вывод информации о вкладе признаков
print("Вклад признаков в главные компоненты:")
for pc, features in zip(['Первая', 'Вторая', 'Третья'], [top_features_pc1, top_features_pc2, top_features_pc3]):
print(f"{pc} главная компонента:")
for feature in features:
if feature < len(numeric_data.columns):
print(f"- {numeric_data.columns[feature]}")
else:
text_index = feature - len(numeric_data.columns)
text_column_index = text_index // vectorized_texts[0].shape[1]
print(f"- Текстовый столбец '{text_columns[text_column_index]}'")
# Метод K-Means
kmeans = KMeans(n_clusters=4)
kmeans_labels = kmeans.fit_predict(pca_data)
kmeans_centers = kmeans.cluster_centers_
# Иерархическая кластеризация
hierarchical = AgglomerativeClustering(n_clusters=4)
hierarchical_labels = hierarchical.fit_predict(pca_data)
# Метод DBSCAN
dbscan = DBSCAN(eps=0.5, min_samples=5)
dbscan_labels = dbscan.fit_predict(pca_data)
# Анализ текстовых данных в кластерах
for cluster in np.unique(kmeans_labels):
cluster_texts = text_data.values[kmeans_labels == cluster]
print(f"Кластер {cluster}:")
# Анализ частоты слов или фраз в кластере
all_texts = ' '.join([' '.join(row) for row in cluster_texts]).split()
top_words = Counter(all_texts).most_common(10)
print(top_words)
print()
# Визуализация результатов кластеризации
# K-Means
fig = plt.figure(figsize=(18, 6))
ax1 = fig.add_subplot(131, projection='3d')
ax1.scatter(pca_data[:, 0], pca_data[:, 1], pca_data[:, 2], c=kmeans_labels, cmap='viridis')
for i, center in enumerate(kmeans_centers):
ax1.scatter(center[0], center[1], center[2], marker='*', s=200, c='black')
ax1.text(center[0], center[1], center[2], f'Кластер {i}', size=10, zorder=1, color='black')
ax1.set_title('K-Means Clustering')
ax1.set_xlabel('Первая главная компонента')
ax1.set_ylabel('Вторая главная компонента')
ax1.set_zlabel('Третья главная компонента')
# Иерархическая кластеризация
ax2 = fig.add_subplot(132, projection='3d')
ax2.scatter(pca_data[:, 0], pca_data[:, 1], pca_data[:, 2], c=hierarchical_labels, cmap='viridis')
# Для иерархической кластеризации центры кластеров не вычисляются напрямую
# Однако, можно вычислить их как среднее значение координат точек в каждом кластере
hierarchical_centers = np.array([pca_data[hierarchical_labels == i].mean(axis=0) for i in np.unique(hierarchical_labels)])
for i, center in enumerate(hierarchical_centers):
ax2.scatter(center[0], center[1], center[2], marker='*', s=200, c='black')
ax2.text(center[0], center[1], center[2], f'Кластер {i}', size=10, zorder=1, color='black')
ax2.set_title('Agglomerative Clustering')
ax2.set_xlabel('Первая главная компонента')
ax2.set_ylabel('Вторая главная компонента')
ax2.set_zlabel('Третья главная компонента')
# DBSCAN
ax3 = fig.add_subplot(133, projection='3d')
ax3.scatter(pca_data[:, 0], pca_data[:, 1], pca_data[:, 2], c=dbscan_labels, cmap='viridis')
# Для DBSCAN центры кластеров не вычисляются напрямую
# Однако, можно вычислить их как среднее значение координат точек в каждом кластере
dbscan_centers = np.array([pca_data[dbscan_labels == i].mean(axis=0) if i != -1 else pca_data[dbscan_labels == i].mean(axis=0) for i in np.unique(dbscan_labels)])
for i, center in enumerate(dbscan_centers):
if i != -1: # Пропускаем шумовые точки
ax3.scatter(center[0], center[1], center[2], marker='*', s=200, c='black')
ax3.text(center[0], center[1], center[2], f'Кластер {i}', size=10, zorder=1, color='black')
ax3.set_title('DBSCAN Clustering')
ax3.set_xlabel('Первая главная компонента')
ax3.set_ylabel('Вторая главная компонента')
ax3.set_zlabel('Третья главная компонента')
plt.tight_layout()
plt.show()
