/
Shundeeva
/
chapter1
Обзор
Документация
Войти
/
Shundeeva
/
chapter1
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
students_performance_analysis.py
302 строки
16 KB
Shundeeva
create: students_performance_analysis.py
29 май 2026, 18:22
Верифицирован
29 май 2026, 18:22
dc7a1fd
Код
Авторство
О чём код?
# -*- coding: utf-8 -*- """ ГЛАВА 1. ДАТАСЕТ С ТАБЛИЧНЫМИ ДАННЫМИ Анализ и подготовка к прогнозированию академической успеваемости Все рисунки 1.1 - 1.14 в правильной последовательности Данные: сначала ищется локальный файл, при отсутствии — скачивается """ import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import plotly.express as px from sklearn.preprocessing import LabelEncoder import os import urllib.request # ===================================================== # НАСТРОЙКА СТИЛЕЙ # ===================================================== sns.set_style("whitegrid") plt.rcParams['figure.figsize'] = (10, 6) plt.rcParams['font.size'] = 12 print("=" * 60) print("ГЕНЕРАЦИЯ РИСУНКОВ ДЛЯ ГЛАВЫ 1") print("=" * 60) # ===================================================== # 1. ЗАГРУЗКА ДАННЫХ (сначала ищем локальный файл) # ===================================================== csv_filename = 'Student_performance_data _.csv' csv_url = 'https://raw.githubusercontent.com/Shundeeva/chapter1/main/Student_performance_data _.csv' # Проверяем, есть ли файл локально if os.path.exists(csv_filename): print(f"✅ Найден локальный файл: {csv_filename}") df = pd.read_csv(csv_filename) else: print(f"⚠️ Локальный файл {csv_filename} не найден.") print(f"📥 Скачиваю с GitHub...") try: urllib.request.urlretrieve(csv_url, csv_filename) print(f"✅ Файл успешно скачан: {csv_filename}") df = pd.read_csv(csv_filename) except Exception as e: print(f"❌ Ошибка скачивания: {e}") print("Пожалуйста, поместите файл вручную в папку со скриптом") raise print(f"✅ Загружено строк: {len(df)}") print(f"Столбцы: {df.columns.tolist()[:10]}...") # ===================================================== # 2. ПОДГОТОВКА ДАННЫХ (адаптация под тему курсовой) # ===================================================== print("\n🔄 Подготовка данных...") # Переименовываем столбцы df = df.rename(columns={ 'GPA': 'потенциал', 'Extracurricular': 'внеклассные_занятия', 'Sports': 'спорт', 'Music': 'музыка', 'Volunteering': 'волонтерство', 'ParentalEducation': 'образование_родителей', 'ParentalSupport': 'поддержка_родителей', 'StudyTimeWeekly': 'время_учёбы', 'Absences': 'пропуски', 'Tutoring': 'репетиторство', 'Age': 'возраст', 'Gender': 'пол', 'Ethnicity': 'этническая_группа' }) # Создаём категорию потенциала df['категория_потенциала'] = pd.cut(df['потенциал'], bins=[0, 2.0, 3.0, 4.0], labels=['низкий', 'средний', 'высокий']) # Создаём признак "участие в мероприятиях" df['участие_в_мероприятиях'] = ((df['внеклассные_занятия'] == 1) | (df['спорт'] == 1) | (df['музыка'] == 1) | (df['волонтерство'] == 1)).map({True: 'да', False: 'нет'}) # Преобразуем пол в читаемый вид df['пол'] = df['пол'].map({1: 'male', 0: 'female'}) print("✅ Данные подготовлены") # ===================================================== # ДАЛЕЕ ВЕСЬ КОД ГЕНЕРАЦИИ РИСУНКОВ # ===================================================== num_cols = ['возраст', 'потенциал', 'время_учёбы', 'пропуски'] # РИСУНОК 1.1 – РАСПРЕДЕЛЕНИЕ ВОЗРАСТА plt.figure(figsize=(10, 6)) plt.hist(df['возраст'], bins=10, edgecolor='black', color='steelblue', alpha=0.7) plt.xlabel('Возраст (лет)') plt.ylabel('Количество студентов') plt.title('Рисунок 1.1 – Диаграмма распределения признака «возраст»') plt.grid(True, alpha=0.3) plt.savefig('figure_1.1_age.png', dpi=150, bbox_inches='tight') plt.show() print("✅ Рисунок 1.1 сохранён") # РИСУНОК 1.2 – РАСПРЕДЕЛЕНИЕ ПОТЕНЦИАЛА (GPA) plt.figure(figsize=(10, 6)) plt.hist(df['потенциал'], bins=20, edgecolor='black', color='green', alpha=0.7) plt.xlabel('Средний балл (GPA)') plt.ylabel('Количество студентов') plt.title('Рисунок 1.2 – Диаграмма распределения признака «потенциал (GPA)»') plt.grid(True, alpha=0.3) plt.savefig('figure_1.2_potential.png', dpi=150, bbox_inches='tight') plt.show() print("✅ Рисунок 1.2 сохранён") # РИСУНОК 1.3 – РАСПРЕДЕЛЕНИЕ ВРЕМЕНИ УЧЁБЫ plt.figure(figsize=(10, 6)) plt.hist(df['время_учёбы'], bins=15, edgecolor='black', color='orange', alpha=0.7) plt.xlabel('Часов учёбы в неделю') plt.ylabel('Количество студентов') plt.title('Рисунок 1.3 – Диаграмма распределения признака «время_учёбы»') plt.grid(True, alpha=0.3) plt.savefig('figure_1.3_study_time.png', dpi=150, bbox_inches='tight') plt.show() print("✅ Рисунок 1.3 сохранён") # РИСУНОК 1.4 – РАСПРЕДЕЛЕНИЕ ПРОПУСКОВ plt.figure(figsize=(10, 6)) plt.hist(df['пропуски'], bins=15, edgecolor='black', color='red', alpha=0.7) plt.xlabel('Количество пропусков') plt.ylabel('Количество студентов') plt.title('Рисунок 1.4 – Диаграмма распределения признака «пропуски»') plt.grid(True, alpha=0.3) plt.savefig('figure_1.4_absences.png', dpi=150, bbox_inches='tight') plt.show() print("✅ Рисунок 1.4 сохранён") # РИСУНОК 1.5 – ЗАВИСИМОСТЬ ПОТЕНЦИАЛА ОТ ПОЛА (boxplot) plt.figure(figsize=(8, 6)) sns.boxplot(data=df, x='пол', y='потенциал') plt.title('Рисунок 1.5 – Зависимость потенциала от пола (boxplot)', fontsize=12) plt.xlabel('Пол') plt.ylabel('Потенциал (GPA)') plt.tight_layout() plt.savefig('figure_1.5_boxplot.png', dpi=150) plt.show() print("✅ Рисунок 1.5 сохранён") # РИСУНОК 1.6 – ВЛИЯНИЕ ВРЕМЕНИ УЧЁБЫ НА ПОТЕНЦИАЛ (scatterplot) plt.figure(figsize=(10, 6)) sns.scatterplot(data=df, x='время_учёбы', y='потенциал', hue='категория_потенциала', alpha=0.6, s=50) plt.title('Рисунок 1.6 – Влияние времени учёбы на потенциал (scatterplot)', fontsize=12) plt.xlabel('Время учёбы в неделю (часы)') plt.ylabel('Потенциал (GPA)') plt.legend(title='Категория потенциала') plt.tight_layout() plt.savefig('figure_1.6_scatter.png', dpi=150) plt.show() print("✅ Рисунок 1.6 сохранён") # РИСУНОК 1.7 – РАСПРЕДЕЛЕНИЕ ПОТЕНЦИАЛА ПО ОБРАЗОВАНИЮ РОДИТЕЛЕЙ (violin plot) plt.figure(figsize=(12, 6)) sns.violinplot(data=df, x='образование_родителей', y='потенциал') plt.title('Рисунок 1.7 – Распределение потенциала по образованию родителей (violin plot)', fontsize=12) plt.xlabel('Уровень образования родителей') plt.ylabel('Потенциал (GPA)') plt.tight_layout() plt.savefig('figure_1.7_violin.png', dpi=150) plt.show() print("✅ Рисунок 1.7 сохранён") # РИСУНОК 1.8 – ИНТЕРАКТИВНЫЙ ГРАФИК (Plotly) fig = px.scatter(df, x='время_учёбы', y='потенциал', color='категория_потенциала', hover_data=['пол', 'образование_родителей', 'участие_в_мероприятиях'], title='Рисунок 1.8 – Интерактивный график: время учёбы vs потенциал') fig.write_html('figure_1.8_interactive.html') fig.show() print("✅ Рисунок 1.8 сохранён (HTML)") # РИСУНОК 1.9 – 3D ВИЗУАЛИЗАЦИЯ (Plotly) fig_3d = px.scatter_3d(df, x='время_учёбы', y='пропуски', z='потенциал', color='категория_потенциала', hover_data=['пол', 'образование_родителей'], title='Рисунок 1.9 – 3D визуализация: время учёбы, пропуски, потенциал') fig_3d.write_html('figure_1.9_3d.html') fig_3d.show() print("✅ Рисунок 1.9 сохранён (HTML)") # РИСУНОК 1.10 – ТЕПЛОВАЯ КАРТА КОРРЕЛЯЦИИ plt.figure(figsize=(8, 6)) corr = df[num_cols].corr() sns.heatmap(corr, annot=True, cmap='coolwarm', fmt='.2f', square=True, annot_kws={'size': 11}) plt.title('Рисунок 1.10 – Тепловая карта корреляционной матрицы Пирсона', fontsize=12) plt.tight_layout() plt.savefig('figure_1.10_correlation.png', dpi=150) plt.show() print("✅ Рисунок 1.10 сохранён") # РИСУНОК 1.11 – ТЕПЛОВАЯ КАРТА ПРОПУЩЕННЫХ ЗНАЧЕНИЙ plt.figure(figsize=(12, 4)) sns.heatmap(df[num_cols + ['пол', 'образование_родителей', 'поддержка_родителей']].isnull(), cbar=False, yticklabels=False, cmap='viridis') plt.title('Рисунок 1.11 – Тепловая карта пропущенных значений', fontsize=12) plt.tight_layout() plt.savefig('figure_1.11_missing.png', dpi=150) plt.show() print("✅ Рисунок 1.11 сохранён") # РИСУНОК 1.12 – ГИСТОГРАММА ПОТЕНЦИАЛА ПОСЛЕ ПРЕОБРАЗОВАНИЙ np.random.seed(42) df['потенциал_шум'] = df['потенциал'] + np.random.normal(0, 0.1, len(df)) plt.figure(figsize=(10, 6)) plt.hist(df['потенциал_шум'], bins=20, color='steelblue', edgecolor='black', alpha=0.7) plt.xlabel('Потенциал (GPA) с добавленным шумом') plt.ylabel('Количество студентов') plt.title('Рисунок 1.12 – Гистограмма распределения потенциала после преобразований') plt.grid(True, alpha=0.3) plt.savefig('figure_1.12_potential_noisy.png', dpi=150, bbox_inches='tight') plt.show() print("✅ Рисунок 1.12 сохранён") # РИСУНОК 1.13 – РАСПРЕДЕЛЕНИЕ ПО ПОЛУ plt.figure(figsize=(8, 6)) gender_counts = df['пол'].value_counts() colors_gender = ['lightblue', 'lightcoral'] bars = plt.bar(gender_counts.index.astype(str), gender_counts.values, color=colors_gender, edgecolor='black') plt.xlabel('Пол') plt.ylabel('Количество студентов') plt.title('Рисунок 1.13 – Распределение наблюдений по полу') for bar, count in zip(bars, gender_counts.values): plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 10, str(count), ha='center', fontsize=12) plt.grid(True, alpha=0.3, axis='y') plt.savefig('figure_1.13_gender.png', dpi=150, bbox_inches='tight') plt.show() print("✅ Рисунок 1.13 сохранён") # РИСУНОК 1.14 – РАСПРЕДЕЛЕНИЕ ПО ОБРАЗОВАНИЮ РОДИТЕЛЕЙ plt.figure(figsize=(10, 6)) parent_counts = df['образование_родителей'].value_counts().sort_index() colors_parent = plt.cm.Blues(np.linspace(0.4, 0.9, len(parent_counts))) bars = plt.bar(parent_counts.index.astype(str), parent_counts.values, color=colors_parent, edgecolor='black') plt.xlabel('Уровень образования родителей') plt.ylabel('Количество студентов') plt.title('Рисунок 1.14 – Распределение наблюдений по уровню образования родителей') for bar, count in zip(bars, parent_counts.values): plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 10, str(count), ha='center', fontsize=10) plt.grid(True, alpha=0.3, axis='y') plt.savefig('figure_1.14_parent_education.png', dpi=150, bbox_inches='tight') plt.show() print("✅ Рисунок 1.14 сохранён") # ===================================================== # АНАЛИЗ ВЫБРОСОВ (Таблица 1.2 в главе) # ===================================================== print("\n" + "=" * 60) print("АНАЛИЗ ВЫБРОСОВ (признак: потенциал)") print("=" * 60) Q1 = df['потенциал'].quantile(0.25) Q3 = df['потенциал'].quantile(0.75) IQR = Q3 - Q1 upper_bound = Q3 + 1.5 * IQR lower_bound = Q1 - 1.5 * IQR outliers = df[(df['потенциал'] < lower_bound) | (df['потенциал'] > upper_bound)].shape[0] print(f"Нижний квартиль (Q1): {Q1:.2f}") print(f"Верхний квартиль (Q3): {Q3:.2f}") print(f"Межквартильный размах (IQR): {IQR:.2f}") print(f"Нижняя граница: {lower_bound:.2f}") print(f"Верхняя граница: {upper_bound:.2f}") print(f"Количество выбросов: {outliers} ({outliers/len(df)*100:.1f}%)") # ===================================================== # ИТОГОВЫЙ СПИСОК ФАЙЛОВ # ===================================================== print("\n" + "=" * 60) print("ВСЕ РИСУНКИ СОЗДАНЫ!") print("=" * 60) print("\n📁 Скачайте эти файлы для вставки в курсовую (Глава 1):") print(" 📷 figure_1.1_age.png – Рисунок 1.1 (возраст)") print(" 📷 figure_1.2_potential.png – Рисунок 1.2 (потенциал)") print(" 📷 figure_1.3_study_time.png – Рисунок 1.3 (время учёбы)") print(" 📷 figure_1.4_absences.png – Рисунок 1.4 (пропуски)") print(" 📷 figure_1.5_boxplot.png – Рисунок 1.5 (пол vs потенциал)") print(" 📷 figure_1.6_scatter.png – Рисунок 1.6 (время учёбы vs потенциал)") print(" 📷 figure_1.7_violin.png – Рисунок 1.7 (образование родителей)") print(" 📷 figure_1.10_correlation.png – Рисунок 1.10 (корреляция)") print(" 📷 figure_1.11_missing.png – Рисунок 1.11 (пропуски)") print(" 📷 figure_1.12_potential_noisy.png – Рисунок 1.12 (после преобразований)") print(" 📷 figure_1.13_gender.png – Рисунок 1.13 (распределение по полу)") print(" 📷 figure_1.14_parent_education.png – Рисунок 1.14 (образование родителей)") print("\n 🌐 figure_1.8_interactive.html – интерактивный график (Plotly)") print(" 🌐 figure_1.9_3d.html – 3D график (Plotly)")