87 lines
2.6 KiB
Python
87 lines
2.6 KiB
Python
"""Conversions et agrégations des mesures de pluie."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
|
|
from meteo.season import SEASON_LABELS
|
|
|
|
from .core import _ensure_datetime_index, _infer_time_step
|
|
|
|
__all__ = ['compute_daily_rainfall_totals', 'compute_rainfall_by_season']
|
|
|
|
|
|
def compute_daily_rainfall_totals(
|
|
df: pd.DataFrame,
|
|
*,
|
|
rate_column: str = "rain_rate",
|
|
) -> pd.DataFrame:
|
|
"""
|
|
Convertit un taux de pluie (mm/h) en cumuls journaliers et cumulés.
|
|
"""
|
|
_ensure_datetime_index(df)
|
|
if rate_column not in df.columns:
|
|
raise KeyError(f"Colonne absente : {rate_column}")
|
|
|
|
series = df[rate_column].fillna(0.0).sort_index()
|
|
if series.empty:
|
|
return pd.DataFrame(columns=["daily_total", "cumulative_total"])
|
|
|
|
time_step = _infer_time_step(series.index)
|
|
diffs = series.index.to_series().diff()
|
|
diffs = diffs.fillna(time_step)
|
|
hours = diffs.dt.total_seconds() / 3600.0
|
|
|
|
rainfall_mm = series.to_numpy(dtype=float) * hours.to_numpy(dtype=float)
|
|
rainfall_series = pd.Series(rainfall_mm, index=series.index)
|
|
|
|
daily_totals = rainfall_series.resample("1D").sum()
|
|
cumulative = daily_totals.cumsum()
|
|
|
|
result = pd.DataFrame(
|
|
{
|
|
"daily_total": daily_totals,
|
|
"cumulative_total": cumulative,
|
|
}
|
|
)
|
|
return result
|
|
|
|
def compute_rainfall_by_season(
|
|
df: pd.DataFrame,
|
|
*,
|
|
rate_column: str = "rain_rate",
|
|
season_column: str = "season",
|
|
) -> pd.DataFrame:
|
|
"""
|
|
Calcule la pluie totale par saison (mm) ainsi que le nombre d'heures pluvieuses.
|
|
"""
|
|
_ensure_datetime_index(df)
|
|
|
|
for col in (rate_column, season_column):
|
|
if col not in df.columns:
|
|
raise KeyError(f"Colonne absente : {col}")
|
|
|
|
data = df[[rate_column, season_column]].copy()
|
|
data[rate_column] = data[rate_column].fillna(0.0)
|
|
data = data.dropna(subset=[season_column])
|
|
if data.empty:
|
|
return pd.DataFrame(columns=["total_rain_mm", "rainy_hours"]).astype(float)
|
|
|
|
time_step = _infer_time_step(data.index)
|
|
diffs = data.index.to_series().diff().fillna(time_step)
|
|
hours = diffs.dt.total_seconds() / 3600.0
|
|
|
|
rainfall_mm = data[rate_column].to_numpy(dtype=float) * hours.to_numpy(dtype=float)
|
|
data["rainfall_mm"] = rainfall_mm
|
|
data["rainy_hours"] = (rainfall_mm > 0).astype(float) * hours.to_numpy(dtype=float)
|
|
|
|
agg = data.groupby(season_column).agg(
|
|
total_rain_mm=("rainfall_mm", "sum"),
|
|
rainy_hours=("rainy_hours", "sum"),
|
|
)
|
|
|
|
order = [season for season in SEASON_LABELS if season in agg.index]
|
|
agg = agg.loc[order]
|
|
return agg
|