/
urfu_itis_limits
/
code-review-101-FAU
Обзор
Документация
Войти
/
urfu_itis_limits
/
code-review-101-FAU
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
master
assignment.py
215 строк
9 KB
FAU
update assignment.py
19 ноя 2025, 11:51
19 ноя 2025, 11:51
19df8bb
Код
Авторство
О чём код?
""" Задание 2: Анализ датасета Wine - ШАБЛОН Цель: Загрузить датасет Wine, провести анализ целевой переменной и признаков ЗАДАЧИ: 1. Загрузить данные в load_data() 2. Вывести информацию о целевой переменной в target_analysis() 3. Вычислить статистику признаков в feature_statistics() 4. Создать графики распределения целевой переменной в visualize_target() 5. Создать гистограммы признаков в visualize_features() 6. Создать boxplots признаков по классам в features_by_target() 7. Вычислить и визуализировать матрицу корреляции в correlation_analysis() """ import matplotlib matplotlib.use('Agg') # 🔒 Обязательно: используем non-interactive backend для CI/Docker import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import load_wine # Настройки шрифтов для поддержки Unicode (в т.ч. кириллицы) plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'Arial', 'sans-serif'] plt.rcParams['axes.unicode_minus'] = False def load_data(): """Загрузить датасет Wine и конвертировать в DataFrame""" data = load_wine() df = pd.DataFrame(data.data, columns=data.feature_names) df['target'] = data.target # Замена числовых меток на названия классов df['class'] = df['target'].map({i: name for i, name in enumerate(data.target_names)}) return df def get_first_n_features(df, n=6): """Вспомогательная функция: получить первые n числовых признаков (без target)""" numeric_cols = df.select_dtypes(include=[np.number]).columns # Исключаем целевую переменную, если она числовая feature_cols = [col for col in numeric_cols if col not in ['target']] return feature_cols[:n] def target_analysis(df): """Анализ целевой переменной (классы вин)""" print("\nРАСПРЕДЕЛЕНИЕ ЦЕЛЕВОЙ ПЕРЕМЕННОЙ (КЛАССОВ ВИНА):") class_counts = df['class'].value_counts().sort_index() total = len(df) print(class_counts) print("\nПроцентное соотношение:") for cls, count in class_counts.items(): pct = (count / total) * 100 print(f"{cls}: {count} ({pct:.1f}%)") return class_counts def feature_statistics(df): """Вычислить статистику по признакам""" print("\nСТАТИСТИКА ПО ПРИЗНАКАМ:") numeric_cols = df.select_dtypes(include=[np.number]).columns.drop(['target']) stats = pd.DataFrame({ 'mean': df[numeric_cols].mean(), 'median': df[numeric_cols].median(), 'std': df[numeric_cols].std(), 'range': df[numeric_cols].max() - df[numeric_cols].min() }) # Округлим до 3 знаков для читаемости stats = stats.round(3) print(stats) return stats def visualize_target(df): """Визуализировать распределение целевой переменной""" plt.figure(figsize=(12, 5)) # Столбчатая диаграмма plt.subplot(1, 2, 1) class_counts = df['class'].value_counts().sort_index() bars = plt.bar(class_counts.index, class_counts.values, color=['#FF9999', '#66B2FF', '#99FF99']) plt.title('Распределение классов вин', fontsize=14) plt.xlabel('Класс') plt.ylabel('Количество образцов') # Добавляем значения над столбцами for bar, count in zip(bars, class_counts.values): plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.5, str(count), ha='center', va='bottom') # Круговая диаграмма plt.subplot(1, 2, 2) plt.pie(class_counts.values, labels=class_counts.index, autopct='%1.1f%%', colors=['#FF9999', '#66B2FF', '#99FF99'], startangle=90) plt.title('Процентное соотношение классов', fontsize=14) plt.tight_layout() plt.savefig('02_wine_target_distribution.png', dpi=150, bbox_inches='tight') plt.close() # ✅ Закрываем фигуру, чтобы не засорять память def visualize_features(df): """Визуализировать распределение признаков (первые 6)""" first_six = get_first_n_features(df, n=6) fig, axes = plt.subplots(3, 2, figsize=(14, 12)) axes = axes.flatten() for i, col in enumerate(first_six): axes[i].hist(df[col], bins=20, color='#66B2FF', edgecolor='black', alpha=0.7) axes[i].set_title(f'{col}', fontsize=12) axes[i].set_xlabel('Значение') axes[i].set_ylabel('Частота') plt.suptitle('Гистограммы распределения первых 6 признаков', fontsize=16) plt.tight_layout(rect=[0, 0.03, 1, 0.95]) plt.savefig('02_wine_features_distribution.png', dpi=150, bbox_inches='tight') plt.close() def features_by_target(df): """Boxplot признаков по классам вин (первые 6 признаков)""" first_six = get_first_n_features(df, n=6) fig, axes = plt.subplots(3, 2, figsize=(14, 12)) axes = axes.flatten() for i, col in enumerate(first_six): # Используем seaborn для красивого boxplot sns.boxplot(data=df, x='class', y=col, ax=axes[i], palette='Set2') axes[i].set_title(f'{col} по классам', fontsize=12) axes[i].set_xlabel('Класс вина') axes[i].set_ylabel('Значение') plt.suptitle('Boxplots признаков по классам вин (первые 6 признаков)', fontsize=16) plt.tight_layout(rect=[0, 0.03, 1, 0.95]) plt.savefig('02_wine_features_by_class.png', dpi=150, bbox_inches='tight') plt.close() def correlation_analysis(df): """Анализ корреляций""" # Выбираем только числовые признаки (без target и class) numeric_cols = df.select_dtypes(include=[np.number]).columns.drop(['target']) corr_matrix = df[numeric_cols].corr() print("\nМАТРИЦА КОРРЕЛЯЦИИ (выборка — верхний правый угол):") # Выведем только сильные корреляции по модулю (> 0.7), кроме диагонали high_corr = [] for i in range(len(corr_matrix.columns)): for j in range(i + 1, len(corr_matrix.columns)): val = corr_matrix.iloc[i, j] if abs(val) > 0.7: high_corr.append((corr_matrix.columns[i], corr_matrix.columns[j], val)) if high_corr: print("Пары признаков с |корреляцией| > 0.7:") for feat1, feat2, r in high_corr: print(f" {feat1} ↔ {feat2}: {r:.3f}") else: print("Нет пар признаков с |корреляцией| > 0.7") # Heatmap plt.figure(figsize=(14, 12)) mask = np.triu(np.ones_like(corr_matrix, dtype=bool)) # маска для верхнего треугольника sns.heatmap(corr_matrix, mask=mask, annot=True, fmt=".2f", cmap='coolwarm', center=0, square=True, cbar_kws={"shrink": .8}, linewidths=0.5) plt.title('Матрица корреляции признаков (тепловая карта)', fontsize=16, pad=20) plt.xticks(rotation=45, ha='right') plt.yticks(rotation=0) plt.tight_layout() plt.savefig('02_wine_correlation_matrix.png', dpi=150, bbox_inches='tight') plt.close() # ✅ Закрываем последнюю фигуру return corr_matrix def main(): """Главная функция""" print("=" * 60) print("ЗАДАНИЕ 2: EXPLORATORY DATA ANALYSIS - WINE DATASET") print("=" * 60) df = load_data() print(f"\nДатасет загружен. Размер: {df.shape}") print("\nПервые 5 строк:") print(df.head()) target_analysis(df) feature_statistics(df) visualize_target(df) visualize_features(df) features_by_target(df) correlation_analysis(df) print("\n" + "=" * 60) print("✅ Анализ завершен! Все графики сохранены.") print("Сохранённые файлы:") print(" • 02_wine_target_distribution.png") print(" • 02_wine_features_distribution.png") print(" • 02_wine_features_by_class.png") print(" • 02_wine_correlation_matrix.png") print("=" * 60) if __name__ == "__main__": main()