Código-fonte para llm4time.core.evaluate.statistics

"""
Módulo para análise estatística de séries temporais.

Este módulo fornece uma classe para calcular estatísticas descritivas
e análises avançadas de séries temporais, incluindo decomposição
de tendência e sazonalidade usando STL.
"""

import numpy as np
import pandas as pd
from statsmodels.tsa.seasonal import STL


[documentos] class Statistics: """ Classe para calcular estatísticas descritivas de séries temporais. Esta classe fornece propriedades para calcular medidas estatísticas robustas de séries temporais, tratando automaticamente valores ausentes e fornecendo análises de tendência e sazonalidade. Args: data (list[float]): Lista de valores numéricos da série temporal. Attributes: data (np.array): Array numpy com todos os dados originais. valid_data (np.array): Array numpy apenas com dados válidos (sem NaN). Examples: >>> data = [10.5, 12.0, np.nan, 15.2, 13.8, 11.1] >>> stats = Statistics(data) >>> stats.mean 12.52 >>> stats.missing_count 1 """
[documentos] def __init__(self, data: list[float]) -> None: """ Inicializa a classe Statistics com dados da série temporal. Args: data (list[float]): Lista de valores numéricos. """ self.data = np.array(data) self.valid_data = np.array(data)[~np.isnan(data)]
@property def mean(self) -> float: """ Calcula a média dos valores válidos. Returns: float: Média arredondada para 4 casas decimais. """ return round(float(np.mean(self.valid_data)), 4) @property def median(self) -> float: """ Calcula a mediana dos valores válidos. Returns: float: Mediana arredondada para 4 casas decimais. """ return round(float(np.median(self.valid_data)), 4) @property def first_quartile(self) -> float: """ Calcula o primeiro quartil (percentil 25) dos valores válidos. Returns: float: Primeiro quartil arredondado para 4 casas decimais. """ return round(float(np.percentile(self.valid_data, 25)), 4) @property def third_quartile(self) -> float: """ Calcula o terceiro quartil (percentil 75) dos valores válidos. Returns: float: Terceiro quartil arredondado para 4 casas decimais. """ return round(float(np.percentile(self.valid_data, 75)), 4) @property def std(self) -> float: """ Calcula o desvio padrão amostral dos valores válidos. Usa ddof=1 para calcular o desvio padrão amostral (divisão por n-1). Returns: float: Desvio padrão arredondado para 4 casas decimais. """ return round(float(np.std(self.valid_data, ddof=1)), 4) @property def min(self) -> float: """ Encontra o valor mínimo dos valores válidos. Returns: float: Valor mínimo arredondado para 4 casas decimais. """ return round(float(np.min(self.valid_data)), 4) @property def max(self) -> float: """ Encontra o valor máximo dos valores válidos. Returns: float: Valor máximo arredondado para 4 casas decimais. """ return round(float(np.max(self.valid_data)), 4) @property def missing_count(self) -> int: """ Conta o número de valores ausentes (NaN) nos dados. Returns: int: Quantidade de valores NaN. """ return int(np.isnan(self.data).sum()) @property def missing_percentage(self) -> float: """ Calcula a porcentagem de valores ausentes nos dados. Returns: float: Percentual de valores NaN arredondado para 4 casas decimais. """ total = len(self.data) missing = self.missing_count return round(float((missing / total) * 100) if total > 0 else 0.0, 4)
[documentos] @staticmethod def trend_seasonality( df: pd.DataFrame, period: int = None, freq: str = None ) -> tuple[pd.Series, pd.Series, pd.Series, float, float]: """ Decompõe uma série temporal em tendência, sazonalidade e resíduo usando STL. Aplica decomposição STL (Seasonal and Trend decomposition using Loess) e calcula a força da tendência e da sazonalidade baseada na variância dos componentes. Args: df (pd.DataFrame): DataFrame contendo colunas "date" e "value". period (int, optional): Período sazonal para STL. Se None, STL infere automaticamente. Defaults to None. freq (str, optional): Frequência da série temporal (ex.: "D", "M", "Q"). Se fornecida, será aplicada via asfreq. Defaults to None. Returns: tuple[pd.Series, pd.Series, pd.Series, float, float]: Tupla contendo: - trend: Componente de tendência estimada - seasonal: Componente sazonal estimado - resid: Resíduo após remoção de tendência e sazonalidade - trend_strength: Força da tendência (0 = fraca, 1 = forte) - seasonality_strength: Força da sazonalidade (0 = fraca, 1 = forte) Examples: >>> data = pd.DataFrame({ ... "date": pd.date_range("2020-01-01", periods=24, freq="M"), ... "value": [i + (i % 12) * 2 for i in range(24)] ... }) >>> trend, seasonal, resid, t_str, s_str = Statistics.trend_seasonality(data, period=12) >>> # Retorna componentes decompostos e forças calculadas """ df = df.copy() # Garantir que a coluna "date" exista e seja datetime if "date" not in df.columns: print("[ERROR] O DataFrame deve conter a coluna 'date'.") return None, None, None, np.nan, np.nan try: df["date"] = pd.to_datetime(df["date"]) df = df.sort_values('date') except Exception as e: print(f"[ERROR] Erro ao converter 'date' para datetime: {e}") return None, None, None, np.nan, np.nan df = df.set_index("date") # Garantir que exista a coluna "value" if "value" not in df.columns: print("[ERROR] O DataFrame deve conter a coluna 'value'.") return None, None, None, np.nan, np.nan # Forçar frequência se for informada if freq is not None: try: df = df.asfreq(freq) except Exception as e: print(f"[ERROR] Erro ao definir frequência '{freq}': {e}") return None, None, None, np.nan, np.nan # Aplicar STL try: stl = STL(df["value"], period=period) if period else STL(df["value"]) res = stl.fit() except Exception as e: print(f"[ERROR] Erro ao aplicar STL: {e}") return None, None, None, np.nan, np.nan trend, seasonal, resid = ( res.trend.round(4), res.seasonal.round(4), res.resid.round(4)) # Cálculo das forças try: var_r = np.var(resid) trend_strength = round( 1 - var_r / np.var(trend + resid), 4 ) if np.var(trend + resid) > 0 else np.nan seasonality_strength = round( 1 - var_r / np.var(seasonal + resid), 4 ) if np.var(seasonal + resid) > 0 else np.nan except Exception as e: print(f"[ERROR] Erro ao calcular forças: {e}") return None, None, None, np.nan, np.nan return trend, seasonal, resid, trend_strength, seasonality_strength