Files
IML_Assignments/Assignment2/Assignment2.ipynb
T
2025-04-13 17:42:00 +03:00

125 KiB

In [1]:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt

def task1_preprocessing() -> None:
    # 1. Загрузка данных
    data = pd.read_csv("dataset/opsd_raw.csv", parse_dates=["utc_timestamp"])
    
    # 2. Выбор релевантных столбцов для Дании
    cols = [
        "utc_timestamp",
        "DK_load_actual_entsoe_transparency",
        "DK_wind_generation_actual", 
        "DK_solar_generation_actual"
    ]
    data = data[cols].copy()
    data.columns = ["timestamp", "load", "wind", "solar"]
    
    # 3. Обработка пропущенных значений
    data = data.interpolate(method="linear", limit_direction="forward")
    
    # 4. Формирование массивов 24x3 (часы × признаки)
    data.set_index("timestamp", inplace=True)
    
    # Группируем по дням и оставляем только дни с ровно 24 записями
    daily_data = (
        data.groupby(data.index.date)  # Группировка по дате
        .filter(lambda x: len(x) == 24)  # Фильтруем группы с ровно 24 строками
        .groupby(data.index.date)  # Повторная группировка по дате
        .apply(lambda x: x[["load", "wind", "solar"]].values.T)  # Преобразуем в массивы
    )
    
    # Преобразуем индексы в формат datetime для дальнейшей работы
    daily_data.index = pd.to_datetime(daily_data.index)
    
    # 5. Создание DataFrame с массивами и метками сезонов
    df = pd.DataFrame({
        "timestamp": daily_data.index,
        "data": daily_data.values,
        "season": daily_data.index.map(lambda x: get_season(x.month))
    })
    
    # 6. Разделение данных
    X = np.stack(df["data"].values)
    y = df["season"].values
    
    X_train, X_temp, y_train, y_temp = train_test_split(
        X, y, test_size=0.3, stratify=y, random_state=42
    )
    X_val, X_test, y_val, y_test = train_test_split(
        X_temp, y_temp, test_size=0.5, stratify=y_temp, random_state=42
    )
    
    # 7. Масштабирование
    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train.reshape(-1, 3)).reshape(X_train.shape)
    X_val_scaled = scaler.transform(X_val.reshape(-1, 3)).reshape(X_val.shape)
    X_test_scaled = scaler.transform(X_test.reshape(-1, 3)).reshape(X_test.shape)
    
    # 8. Сохранение данных
    np.savez("processed_data.npz",
             X_train=X_train_scaled,
             X_val=X_val_scaled,
             X_test=X_test_scaled,
             y_train=y_train,
             y_val=y_val,
             y_test=y_test)
    
    # 9. Визуализация
    plot_sample_profiles(df)

def get_season(month: int) -> str:
    if month in [12, 1, 2]: return "winter"
    if month in [3, 4, 5]: return "spring"
    if month in [6, 7, 8]: return "summer"
    return "autumn"

def plot_sample_profiles(df: pd.DataFrame) -> None:
    plt.figure(figsize=(12, 6))
    for season in ["winter", "spring", "summer", "autumn"]:
        sample = df[df["season"] == season].iloc[0]["data"]
        plt.plot(sample[0], label=f"{season} load")
    plt.title("Суточные профили потребления энергии по сезонам")
    plt.xlabel("Час дня (0-23)")
    plt.ylabel("Мощность (МВт)")
    plt.legend()
    plt.grid(True)
    plt.savefig("load_profiles.png")
    plt.show()

# Запуск preprocessing
task1_preprocessing()