import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from sklearn.metrics import r2_score from scipy import stats # === ЗАГРУЗКА ДАННЫХ === columns = ['Position', 'Height(inches)', 'Weight(pounds)', 'Age'] df = pd.read_csv('SOCR_Data_MLB_HeightsWeights.txt', sep='\t', nrows=115, usecols=columns) # === ПАРНАЯ РЕГРЕССИЯ === # Выходная переменная — вес, входная — рост X_single = df['Height(inches)'].values.reshape(-1, 1) y = df['Weight(pounds)'].values lr = LinearRegression().fit(X_single, y) y_pred_single = lr.predict(X_single) res_single = y - y_pred_single # Визуализация fig1, axes = plt.subplots(1, 3, figsize=(15, 5)) fig1.suptitle('Парная регрессия') # 1. Линия регрессии axes[0].scatter(df['Height(inches)'], df['Weight(pounds)'], color='blue', alpha=0.6) axes[0].plot(df['Height(inches)'], y_pred_single, color='red', linewidth=2) axes[0].set_xlabel('Height (inches)') axes[0].set_ylabel('Weight (pounds)') axes[0].set_title('Линейная зависимость') # 2. Остатки axes[1].scatter(y_pred_single, res_single, color='green', alpha=0.6) axes[1].axhline(y=0, color='red', linestyle='--') axes[1].set_xlabel('Предсказанные значения') axes[1].set_ylabel('Остатки') axes[1].set_title('Анализ остатков') # 3. Гистограмма остатков axes[2].hist(res_single, bins=15, color='gray', edgecolor='black') axes[2].set_xlabel('Остатки') axes[2].set_ylabel('Количество точек') axes[2].set_title('Распределение остатков') # Метрики Qreg = np.sum((y_pred_single - y.mean()) ** 2) Qres = np.sum((y - y_pred_single) ** 2) Qtotal = np.sum((y - y.mean()) ** 2) R2 = r2_score(y, y_pred_single) AdjR2 = 1 - (1 - R2) * (115 - 1) / (115 - 1 - 1) R = np.sqrt(R2) StdErr = np.sqrt(Qres / (115 - 2)) print('\n=== Парная регрессия ===') print('Коэффициент детерминации R²:', round(R2, 4)) print('Скорректированный R²:', round(AdjR2, 4)) print('Множественный коэффициент корреляции R:', round(R, 4)) print('Стандартная ошибка регрессии:', round(StdErr, 4)) print('Коэффициенты модели (b0 + b1*x):', lr.intercept_, lr.coef_) # === МНОЖЕСТВЕННАЯ РЕГРЕССИЯ === # Кодируем категориальный признак Position в числовой формат position_mapping = {pos: i for i, pos in enumerate(df['Position'].unique())} df['Position_num'] = df['Position'].map(position_mapping) # Входные переменные — позиция, рост и возраст X_multi = df[['Position_num', 'Height(inches)', 'Age']].values mr = LinearRegression().fit(X_multi, y) y_pred_multi = mr.predict(X_multi) res_multi = y - y_pred_multi # Визуализация fig2, axes = plt.subplots(1, 2, figsize=(12, 5)) fig2.suptitle('Множественная регрессия') # Остатки axes[0].scatter(y_pred_multi, res_multi, color='purple', alpha=0.6) axes[0].axhline(y=0, color='red', linestyle='--') axes[0].set_xlabel('Предсказанные значения') axes[0].set_ylabel('Остатки') axes[0].set_title('Анализ остатков') # Гистограмма остатков axes[1].hist(res_multi, bins=15, color='orange', edgecolor='black') axes[1].set_xlabel('Остатки') axes[1].set_ylabel('Количество точек') axes[1].set_title('Распределение остатков') # Метрики Qreg_m = np.sum((y_pred_multi - y.mean()) ** 2) Qres_m = np.sum((y - y_pred_multi) ** 2) R2_m = r2_score(y, y_pred_multi) AdjR2_m = 1 - (1 - R2_m) * (115 - 1) / (115 - 3 - 1) R_m = np.sqrt(R2_m) StdErr_m = np.sqrt(Qres_m / (115 - 3 - 1)) print('\n=== Множественная регрессия ===') print('Коэффициент детерминации R²:', round(R2_m, 4)) print('Скорректированный R²:', round(AdjR2_m, 4)) print('Множественный коэффициент корреляции R:', round(R_m, 4)) print('Стандартная ошибка регрессии:', round(StdErr_m, 4)) print('Коэффициенты модели:', mr.intercept_, mr.coef_) plt.tight_layout() plt.show() # === КРАТКИЕ ВЫВОДЫ === print('\n=== ВЫВОДЫ ===') print('1. Парная регрессия показывает умеренную связь между ростом и весом (R ≈', round(R, 2), ').') print('2. Множественная регрессия с учётом возраста и позиции улучшает качество модели (R² выше).') print('3. Остатки распределены примерно нормально, значимых выбросов немного.') print('4. Наиболее информативные переменные: рост и возраст.')