import pandas as pd
import numpy as np
from itertools import combinations
from google.colab import files

# Загружаем датасет
#uploaded = files.upload()

# Предполагаем, что загружаемый вами файл имеет имя diseasesDataset-_-kopia.xlsx
df = pd.read_excel('diseasesDataset__kopia.xlsx', engine='openpyxl')

# Проверьте, как выглядят ваши данные
# print("Первые 5 строк вашего датасета:")
# print(df.head())


# 1. Функциональная предобработка данных (попарные произведения)
def add_interaction_terms(df):
    factors = df.columns[1:]  # Пропускаем целевую колонку
    for (f1, f2) in combinations(factors, 2):
        df[f"{f1}_{f2}"] = df[f1] * df[f2]
    return df

df = add_interaction_terms(df)

# Корреляция между факторами
correlation_matrix = df.corr()

# 2. Определение групп по корреляции
def define_correlation_groups(corr_matrix, target_factor):
    strong_group = []
    medium_group = []
    weak_group = []

    for factor in corr_matrix.columns:
        if factor != target_factor:
            corr_value = corr_matrix[target_factor][factor]
            if 0.7 < corr_value <= 1:
                strong_group.append(factor)
            elif 0.3 < corr_value <= 0.7:
                medium_group.append(factor)
            elif 0 <= corr_value <= 0.3:
                weak_group.append(factor)

    return strong_group, medium_group, weak_group

# Используем целевую переменную
target_factor = '№2 ВРОЖДЕННЫЕ АНОМАЛИИ'
strong, medium, weak = define_correlation_groups(correlation_matrix, target_factor)

print(f"Сильная корреляция: {strong}")
print(f"Средняя корреляция: {medium}")
print(f"Слабая корреляция: {weak}")

# 3. Вычисление коэффициентов корреляции для сильной группы
def calculate_coefficients(strong_group, target_series):
    coefficients = {}
    for factor in strong_group:
        r = correlation_matrix[target_series.name][factor]
        sigma_y = target_series.std()
        sigma_x = df[factor].std()
        b = r * (sigma_y / sigma_x)
        a = target_series.mean() - b * df[factor].mean()
        coefficients[factor] = (a, b)

    return coefficients

# Пример использования
coefficients_strong = calculate_coefficients(strong, df[target_factor])
# print("Коэффициенты для сильной группы:")
# for factor, (a, b) in coefficients_strong.items():
#     print(f"{factor}: a = {a}, b = {b}")

# 4. Определение эмпирических и теоретических областей
def calculate_empirical_theoretical_bounds(factor_series):
    a = factor_series.min()
    b = factor_series.max()
    min_empirical = a - (b - a) * 0.05
    max_empirical = b + (b - a) * 0.05
    mean = factor_series.mean()
    std = factor_series.std()
    min_theoretical = mean - 3 * std
    max_theoretical = mean + 3 * std
    return (min_empirical, max_empirical), (min_theoretical, max_theoretical)

# Пример использования для каждого фактора в df
for factor in df.columns:
    empirical_bounds, theoretical_bounds = calculate_empirical_theoretical_bounds(df[factor])
    print(f"Фактор: {factor}")
    print(f"Эмпирическая область: {empirical_bounds}")
    print(f"Теоретическая область: {theoretical_bounds}")
    print("------------------------")


#2
# БЛОК 1: Расширение управляющих факторов
def add_interaction_terms(df, order=2):
    factors = df.columns
    if order >= 2:
        for (f1, f2) in combinations(factors, 2):
            df[f"{f1}_{f2}"] = df[f1] * df[f2]
    if order >= 3:
        for (f1, f2, f3) in combinations(factors, 3):
            df[f"{f1}_{f2}_{f3}"] = df[f1] * df[f2] * df[f3]
    return df

# Пример добавления попарных и троичных произведений
df = add_interaction_terms(df, order=3)

# БЛОК 2: Функциональная предобработка данных
def functional_preprocessing(df, target):
    for col in df.columns:
        if col == target:
            continue
        original_corr = df[target].corr(df[col])
        best_corr = original_corr

        # Здесь вы можете добавить проверки на изменение коэффициента корреляции
        # Например, применить функцию 1/x на колонки
        if np.all(df[col] > 0):  # Проверка на ноли, иначе 1/x
            transformed_col = 1 / df[col]
            new_corr = df[target].corr(transformed_col)
            if new_corr > best_corr:
                df[col] = transformed_col
                best_corr = new_corr

    return df

# Применение функциональной предобработки
df = functional_preprocessing(df, 'x_1')

# БЛОК 3: Построение многомерных регрессионных уравнений
import statsmodels.api as sm

def build_regression_model(df, target):
    X = df.drop(columns=[target])
    y = df[target]
    X = sm.add_constant(X)  # Добавляем константу для свободного члена
    model = sm.OLS(y, X).fit()
    return model

# Построение модели для y
model = build_regression_model(df, 'x_1')
print(model.summary())

# БЛОК 4: Проверка адекватности модели
def check_model_diagnosis(model):
    residuals = model.resid
    mean_residuals = np.mean(residuals)
    std_residuals = np.std(residuals)
    skewness = stats.skew(residuals)
    kurtosis = stats.kurtosis(residuals)

    #print("Среднее ошибка:", mean_residuals)
    #print("Стандартное отклонение ошибки:", std_residuals)
    #print("Коэффициент асимметрии:", skewness)
    #print("Коэффициент эксцесса:", kurtosis)

check_model_diagnosis(model)

# БЛОК 5: Установка области определения
def calculate_bounds(series):
    a = series.min()
    b = series.max()
    empirical_min = a - (b - a) * 0.05
    empirical_max = b + (b - a) * 0.05
    theoretical_mean = series.mean()
    theoretical_std = series.std()
    theoretical_min = theoretical_mean - 3 * theoretical_std
    theoretical_max = theoretical_mean + 3 * theoretical_std

    return (max(empirical_min, theoretical_min), min(empirical_max, theoretical_max))

# Применение для каждого фактора
for factor in df.columns:
    bounds = calculate_bounds(df[factor])
    #print(f"Область определения для {factor}:", bounds)

# Завершение

Этот код работает слишком долго на моем датасете. Проведи оптимизицаю, но функциональности не меняй. В конце сделай вывод модели в виде "y = ..."