1

Premières analyses de corrélation

This commit is contained in:
Richard Dern 2025-11-17 14:59:59 +01:00
parent 62a928ec85
commit 5a546688f1
36 changed files with 631 additions and 0 deletions

124
docs/08 - Corrélations.md Normal file
View File

@ -0,0 +1,124 @@
# Corrélations
## Matrice de corrélation
| | Température | Humidité relative | Pression atm. | Précipitations | Luminance | Vitesse du vent | Direction du vent |
| --------------------- | ----------- | ----------------- | ------------- | -------------- | --------- | --------------- | ----------------- |
| **Température** | — | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| **Humidité relative** | ✅ | — | ✅ | ✅ | ✅ | ❌ | ❌ |
| **Pression atm.** | ✅ | ✅ | — | ✅ | ✅ | ✅ | ✅ |
| **Précipitations** | ✅ | ✅ | ✅ | — | ✅ | ✅ | ✅ |
| **Luminance** | ✅ | ✅ | ✅ | ✅ | — | ❌ | ❌ |
| **Vitesse du vent** | ❌ | ❌ | ✅ | ✅ | ❌ | — | ❌ |
| **Direction du vent** | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | — |
## Température ↔ Humidité relative ✅
Lhumidité relative (HR) est, par définition, le rapport entre la quantité de vapeur deau réellement présente dans lair et la quantité maximale quil pourrait contenir à cette température. Cette “quantité maximale” est donnée par la pression de vapeur saturante, qui augmente de façon quasi exponentielle avec la température, selon la relation de ClausiusClapeyron.([asclimateservices.org][1])
Conséquences directes :
- si la quantité absolue de vapeur deau reste constante et que la température **augmente**, la pression de vapeur saturante augmente encore plus vite → lair devient proportionnellement **moins humide** (HR diminue) ;
- si la température **baisse** sans changement dhumidité absolue, lair se rapproche de la saturation → HR **augmente**.
On sattend donc à une relation forte et systématique entre température et humidité relative : même sans changement de masse dair, le simple réchauffement/refroidissement diurne suffit à faire varier lHR.
## Pression atmosphérique ↔ Temps sensible, humidité, précipitations ✅
En surface, la pression atmosphérique organise la circulation de lair et la formation des systèmes météo (anticyclones et dépressions). Les centres de **basse pression** sont associés à de lair qui converge en surface et sélève, se refroidit, et condense sa vapeur deau en nuages et précipitations. À linverse, les **hautes pressions** sont associées à de lair qui descend, se réchauffe et se dessèche, donnant du temps généralement sec et dégagé.([Centre pour l'Éducation Scientifique][2])
Doù plusieurs liens attendus :
- **Pression ↔ Précipitations**
Dépressions (basse pression) → air ascendant, condensation, nuages, pluies ; anticyclones (haute pression) → air subsident, ciel souvent dégagé et précipitations rares. Des études relient explicitement les quantités de précipitations aux variations de pression au passage de systèmes météo.([ResearchGate][3])
- **Pression ↔ Humidité relative**
Les basses pressions saccompagnent souvent dair plus humide (nuages épais, air proche de la saturation), les hautes pressions dair plus sec, surtout en basses couches. Ce nest pas une loi exacte point par point, mais climatologiquement très robuste.([Cordulus][4])
- **Pression ↔ Luminance**
Anticyclones → ciel dégagé, ensoleillement fort, grande amplitude thermique jour/nuit ; dépressions → couverture nuageuse, lumière atténuée et plus diffuse, températures lissées.([Wikipédia][5])
- **Pression ↔ Température**
Pression, température et densité de lair sont reliées par léquation détat (air quasi parfait). Dans la pratique, les systèmes de haute pression sont souvent associés à des nuits plus froides (refroidissement radiatif sous ciel dégagé) et des journées plus chaudes, tandis que les basses pressions limitent les contrastes via les nuages et les précipitations.([Wikipédia][5])
## Pression ↔ Vent (vitesse & direction) ✅
Le vent est essentiellement une réponse de lair aux **gradients de pression** : lair tend à se déplacer des zones de haute pression vers les zones de basse pression. La force de ce mouvement dépend de la pente du “relief de pression” (gradient de pression), et sa direction est fortement influencée par la force de Coriolis.([ESS][6])
- **Vitesse du vent ↔ Pression**
Plus les isobares (lignes dégale pression) sont serrées, plus le gradient de pression est fort, et plus le vent est rapide. Le vent “géostrophique”, solution idéale de léquilibre entre gradient de pression et Coriolis, donne une bonne approximation de cette relation : vitesse du vent proportionnelle au gradient de pression.([Wikipédia][7])
- **Direction du vent ↔ Pression**
En régime moyen, le vent souffle approximativement **parallèle aux isobares**, avec les basses pressions à sa gauche dans lhémisphère Nord (droite dans lhémisphère Sud), conformément à léquilibre géostrophique. La direction du vent est donc un reflet direct de la disposition des centres de haute et basse pression autour du point dobservation.([Wikipédia][7])
## Précipitations ↔ Humidité & Température ✅
Les précipitations sont la manifestation macroscopique de la condensation de vapeur deau en gouttes suffisamment grosses pour tomber. Il y a donc un lien très direct avec le contenu en eau de latmosphère et la température :
- **Humidité ↔ Précipitations**
Pour quil pleuve, il faut que lair atteigne (localement) la saturation : humidité relative proche de 100 %. Lorsque des systèmes dépressionnaires ou des fronts forcent lascendance de lair, celui-ci se refroidit, sa vapeur deau condense et la saturation est atteinte → formation de nuages et de pluie.([NCICS][8])
- **Température ↔ Précipitations**
La capacité de lair à contenir de la vapeur deau augmente denviron 67 % par degré de réchauffement, selon la relation de ClausiusClapeyron.([asclimateservices.org][1])
À teneur en humidité relative comparable, un air plus chaud peut donc alimenter des précipitations plus intenses. La phase de la précipitation (neige, pluie, pluie verglaçante) dépend aussi directement de la température dans la colonne dair.
## Nuages, Luminance & Pluie ✅
Le capteur de luminance mesure essentiellement léclairement lumineux en surface, lui-même directement lié au rayonnement solaire incident. Ce dernier est contrôlé par la hauteur du Soleil, mais aussi très fortement par la **nébulosité** (nuages) et, dans une moindre mesure, les aérosols.
- **Luminance ↔ Précipitations**
Les situations pluvieuses sont presque toujours associées à des nuages épais et/ou profonds (stratiformes, cumulonimbus). Ces nuages réduisent nettement le rayonnement direct et donc la luminance mesurée en surface, même sil existe des cas particuliers de “silver lining” où le rayonnement diffus peut être localement renforcé.([American Meteorological Society Journals][9])
- **Luminance ↔ Humidité / Pression / Température**
Plus généralement, les jours anticycloniques secs et stables (haute pression) sont caractérisés par une forte luminance en journée ; à linverse, les situations dépressionnaires humides (basse pression, air proche de la saturation) se traduisent par une baisse significative de léclairement au sol.([Wikipédia][5])
## Vent ↔ Précipitations ✅
Les épisodes pluvieux marqués (passage de fronts, lignes de grains, orages) sont fréquemment associés à :
- une augmentation de la **vitesse du vent**, liée au gradient de pression plus fort autour des systèmes dépressionnaires et aux courants descendantes / rafales convectives ;
- des **directions de vent caractéristiques** pour un site donné (par exemple flux douest ou de sud-ouest apportant de lair maritime humide sur la France).
Les études climatologiques et les diagnostics synoptiques mettent systématiquement en avant cette co-occurrence entre précipitations, gradients de pression marqués et vents plus forts.([NCICS][8])
Pour autant, la relation nest pas parfaitement déterministe : on peut avoir du vent sans pluie (front sec, mistral, tramontane…), et des pluies faibles sous vents modestes. On parle donc plutôt de **tendance statistique robuste** que de loi exacte.
## Pourquoi des ❌ dans la matrice ?
Les ❌ ne signifient pas “aucune relation possible”, mais :
> “Il nexiste pas de relation simple, universelle, monotone entre ces deux grandeurs, valable partout et tout le temps.”
Quelques exemples :
- **Température ↔ Vitesse / Direction du vent**
Le vent dépend de gradients horizontaux de pression et de température à grande échelle, pas de la valeur de la température locale à votre station. Vous pouvez avoir une journée très chaude sans vent, ou un refroidissement brutal par intrusion dair froid très venteux : la relation locale instantanée nest pas simple.
- **Luminance ↔ Vent**
On peut avoir un grand soleil avec un vent soutenu (temps anticyclonique venteux), ou un ciel uniformément gris et quasi sans vent. Lien, encore une fois, via la situation météo densemble, pas directement entre “lumière” et “vitesse de lair”.
- **Vent ↔ Humidité / Température ↔ Direction du vent** ❌ (au sens général)
Sur **un site donné**, il est fréquent dobserver que certains secteurs de vent (advections maritimes, continentales, montagne/plaine, etc.) sont associés à des signatures de température ou dhumidité typiques : cest le “climat local” des masses dair.
Mais ce pattern dépend énormément de la géographie. Il nexiste pas, par exemple, de règle universelle “vent du nord = air sec” valable partout sur Terre. Doù le ❌ au sens “relation globale, généralisable”.
---
Toutes ces corrélations sont explorées par les scripts `scripts/plot_all_pairwise_scatter.py` et `scripts/plot_lagged_correlations.py`, qui vont produire des graphiques dans `figures/pairwise_scatter` et `figures/lagged_correlations`. Mais, bien qu'intéressantes et instructives, ces images sont encore primitives.
Néanmoins, un graphique de type "heatmap" permet déjà de quantifier ces corrélations en se basant sur les données concrètes :
```shell
python -m scripts.plot_correlation_heatmap
```
![](../figures/correlation_heatmap.png)
[1]: https://asclimateservices.org/code-and-equations/clausius-clapeyron/?utm_source=chatgpt.com "Clausius Clapeyron"
[2]: https://scied.ucar.edu/learning-zone/how-weather-works/highs-and-lows-air-pressure?utm_source=chatgpt.com "The Highs and Lows of Air Pressure"
[3]: https://www.researchgate.net/publication/323079756_A_generalized_relationship_between_atmospheric_pressure_and_precipitation_associated_with_a_passing_weather_system?utm_source=chatgpt.com "A generalized relationship between atmospheric pressure ..."
[4]: https://www.cordulus.com/glossary/atmospheric-pressure?utm_source=chatgpt.com "What is Atmospheric pressure?"
[5]: https://en.wikipedia.org/wiki/Pressure_system?utm_source=chatgpt.com "Pressure system"
[6]: https://www.ess.uci.edu/~yu/class/ess55/lecture.4.motion.all.pdf?utm_source=chatgpt.com "Lecture 4: Pressure and Wind"
[7]: https://en.wikipedia.org/wiki/Geostrophic_wind?utm_source=chatgpt.com "Geostrophic wind"
[8]: https://ncics.org/cics-news/quantifying-the-relationship-between-extreme-precipitation-and-atmospheric-water-vapor/?utm_source=chatgpt.com "Quantifying the Relationship Between Extreme ..."
[9]: https://journals.ametsoc.org/view/journals/apme/42/10/1520-0450_2003_042_1421_ccboai_2.0.co_2.xml?utm_source=chatgpt.com "Cloud Coverage Based on All-Sky Imaging and Its Impact on ..."

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

117
meteo/analysis.py Normal file
View File

@ -0,0 +1,117 @@
# meteo/analysis.py
from __future__ import annotations
from typing import Literal
import numpy as np
import pandas as pd
from .variables import Variable
def compute_correlation_matrix(
df: pd.DataFrame,
*,
method: Literal["pearson", "spearman"] = "pearson",
) -> pd.DataFrame:
"""
Calcule la matrice de corrélation entre toutes les colonnes numériques
du DataFrame.
Attention :
- La direction du vent est traitée ici comme une variable scalaire 0360°,
ce qui n'est pas idéal pour une analyse circulaire. On affinera plus tard
si besoin (représentation en sin/cos).
"""
numeric_df = df.select_dtypes(include=["number"])
corr = numeric_df.corr(method=method)
return corr
def compute_correlation_matrix_for_variables(
df: pd.DataFrame,
variables: Sequence[Variable],
*,
method: Literal["pearson", "spearman"] = "pearson",
) -> pd.DataFrame:
"""
Calcule la matrice de corrélation pour un sous-ensemble de variables,
dans un ordre bien défini.
Paramètres
----------
df :
DataFrame contenant les colonnes à analyser.
variables :
Séquence de Variable décrivant les colonnes à prendre en compte.
method :
Méthode de corrélation pandas (pearson, spearman, ...).
Retour
------
DataFrame :
Matrice de corrélation, index et colonnes dans le même ordre que
`variables`, avec les colonnes pandas correspondant aux noms de colonnes
du DataFrame (ex: "temperature", "humidity", ...).
"""
columns = [v.column for v in variables]
missing = [c for c in columns if c not in df.columns]
if missing:
raise KeyError(f"Colonnes manquantes dans le DataFrame : {missing!r}")
numeric_df = df[columns].astype(float)
corr = numeric_df.corr(method=method)
# On s'assure de l'ordre
corr = corr.loc[columns, columns]
return corr
def compute_lagged_correlation(
df: pd.DataFrame,
var_x: Variable,
var_y: Variable,
*,
max_lag_minutes: int = 360,
step_minutes: int = 10,
method: Literal["pearson", "spearman"] = "pearson",
) -> pd.DataFrame:
"""
Calcule la corrélation entre deux variables pour une série de décalages
temporels (lags).
Convention :
- lag > 0 : X "précède" Y de `lag` minutes.
On corrèle X(t) avec Y(t + lag).
- lag < 0 : Y "précède" X de |lag| minutes.
On corrèle X(t) avec Y(t + lag), lag étant négatif.
Implémentation :
- On utilise un DataFrame avec les deux colonnes,
puis on applique un `shift` sur Y.
"""
if var_x.column not in df.columns or var_y.column not in df.columns:
raise KeyError("Les colonnes demandées ne sont pas présentes dans le DataFrame.")
series_x = df[var_x.column]
series_y = df[var_y.column]
lags = range(-max_lag_minutes, max_lag_minutes + 1, step_minutes)
results: list[tuple[int, float]] = []
for lag in lags:
# Y décalé de -lag : pour lag positif, on corrèle X(t) à Y(t + lag)
shifted_y = series_y.shift(-lag)
pair = pd.concat([series_x, shifted_y], axis=1).dropna()
if pair.empty:
corr = np.nan
else:
corr = pair.iloc[:, 0].corr(pair.iloc[:, 1], method=method)
results.append((lag, corr))
lag_df = pd.DataFrame(results, columns=["lag_minutes", "correlation"])
lag_df = lag_df.set_index("lag_minutes")
return lag_df

149
meteo/plots.py Normal file
View File

@ -0,0 +1,149 @@
# meteo/plots.py
from __future__ import annotations
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from .variables import Variable
def plot_scatter_pair(
df: pd.DataFrame,
var_x: Variable,
var_y: Variable,
output_path: str | Path,
*,
sample_step: int = 10,
) -> Path:
"""
Trace un nuage de points (scatter) pour une paire de variables.
- On sous-échantillonne les données avec `sample_step` (par exemple,
1 point sur 10) pour éviter un graphique illisible.
"""
output_path = Path(output_path)
output_path.parent.mkdir(parents=True, exist_ok=True)
# On ne garde que les colonnes pertinentes et les lignes complètes
df_pair = df[[var_x.column, var_y.column]].dropna()
if sample_step > 1:
df_pair = df_pair.iloc[::sample_step, :]
plt.figure()
plt.scatter(df_pair[var_x.column], df_pair[var_y.column], s=5, alpha=0.5)
plt.xlabel(f"{var_x.label} ({var_x.unit})")
plt.ylabel(f"{var_y.label} ({var_y.unit})")
plt.title(f"{var_y.label} en fonction de {var_x.label}")
plt.tight_layout()
plt.savefig(output_path, dpi=150)
plt.close()
return output_path.resolve()
def plot_lagged_correlation(
lag_df: pd.DataFrame,
var_x: Variable,
var_y: Variable,
output_path: str | Path,
) -> Path:
"""
Trace la corrélation en fonction du lag (en minutes) entre deux variables.
"""
output_path = Path(output_path)
output_path.parent.mkdir(parents=True, exist_ok=True)
plt.figure()
plt.plot(lag_df.index, lag_df["correlation"])
plt.axvline(0, linestyle="--") # lag = 0
plt.xlabel("Décalage (minutes)\n(lag > 0 : X précède Y)")
plt.ylabel("Corrélation")
plt.title(f"Corrélation décalée : {var_x.label}{var_y.label}")
plt.grid(True)
plt.tight_layout()
plt.savefig(output_path, dpi=150)
plt.close()
return output_path.resolve()
def plot_correlation_heatmap(
corr: pd.DataFrame,
variables: Sequence[Variable],
output_path: str | Path,
*,
annotate: bool = True,
) -> Path:
"""
Trace une heatmap de la matrice de corrélation.
Paramètres
----------
corr :
Matrice de corrélation (index et colonnes doivent correspondre
aux noms de colonnes des variables).
variables :
Liste de Variable, dans l'ordre où elles doivent apparaître.
output_path :
Chemin du fichier image à écrire.
annotate :
Si True, affiche la valeur numérique dans chaque case.
"""
output_path = Path(output_path)
output_path.parent.mkdir(parents=True, exist_ok=True)
columns = [v.column for v in variables]
labels = [v.label for v in variables]
# On aligne la matrice sur l'ordre désiré
corr = corr.loc[columns, columns]
data = corr.to_numpy()
fig, ax = plt.subplots()
im = ax.imshow(data, vmin=-1.0, vmax=1.0)
# Ticks et labels
ax.set_xticks(np.arange(len(labels)))
ax.set_yticks(np.arange(len(labels)))
ax.set_xticklabels(labels, rotation=45, ha="right")
ax.set_yticklabels(labels)
# Axe en haut/bas selon préférence (ici on laisse en bas)
ax.set_title("Matrice de corrélation (coef. de Pearson)")
# Barre de couleur
cbar = plt.colorbar(im, ax=ax)
cbar.set_label("Corrélation")
# Annotation des cases
if annotate:
n = data.shape[0]
for i in range(n):
for j in range(n):
if i == j:
text = ""
else:
val = data[i, j]
if np.isnan(val):
text = ""
else:
text = f"{val:.2f}"
ax.text(
j,
i,
text,
ha="center",
va="center",
)
plt.tight_layout()
plt.savefig(output_path, dpi=150)
plt.close(fig)
return output_path.resolve()

82
meteo/variables.py Normal file
View File

@ -0,0 +1,82 @@
# meteo/variables.py
from __future__ import annotations
from dataclasses import dataclass
from typing import Dict, List
@dataclass(frozen=True)
class Variable:
"""
Décrit une variable météorologique exploitable dans les analyses.
- key : identifiant interne (stable, sans espace)
- column : nom de la colonne dans le DataFrame
- label : libellé humain pour les graphiques
- unit : unité d'affichage (texte libre)
"""
key: str
column: str
label: str
unit: str
VARIABLES: List[Variable] = [
Variable(
key="temperature",
column="temperature",
label="Température",
unit="°C",
),
Variable(
key="humidity",
column="humidity",
label="Humidité relative",
unit="%",
),
Variable(
key="pressure",
column="pressure",
label="Pression atmosphérique",
unit="hPa",
),
Variable(
key="rain_rate",
column="rain_rate",
label="Précipitations",
unit="mm/h",
),
Variable(
key="illuminance",
column="illuminance",
label="Luminance",
unit="lx",
),
Variable(
key="wind_speed",
column="wind_speed",
label="Vitesse du vent",
unit="km/h",
),
Variable(
key="wind_direction",
column="wind_direction",
label="Direction du vent",
unit="°",
),
]
VARIABLES_BY_KEY: Dict[str, Variable] = {v.key: v for v in VARIABLES}
def iter_variable_pairs() -> list[tuple[Variable, Variable]]:
"""
Retourne la liste de toutes les paires (i, j) avec i < j, pour
éviter les doublons et les diagonales.
"""
pairs: list[tuple[Variable, Variable]] = []
for i, vi in enumerate(VARIABLES):
for vj in VARIABLES[i + 1 :]:
pairs.append((vi, vj))
return pairs

View File

@ -0,0 +1,45 @@
# scripts/plot_all_pairwise_scatter.py
from __future__ import annotations
from pathlib import Path
from meteo.dataset import load_raw_csv
from meteo.variables import iter_variable_pairs
from meteo.plots import plot_scatter_pair
CSV_PATH = Path("data/weather_minutely.csv")
OUTPUT_DIR = Path("figures/pairwise_scatter")
def main() -> None:
if not CSV_PATH.exists():
print(f"⚠ Fichier introuvable : {CSV_PATH}")
return
df = load_raw_csv(CSV_PATH)
print(f"Dataset minuté chargé : {CSV_PATH}")
print(f" Lignes : {len(df)}")
print(f" Colonnes : {list(df.columns)}")
pairs = iter_variable_pairs()
print(f"Nombre de paires de variables : {len(pairs)}")
for var_x, var_y in pairs:
filename = f"scatter_{var_x.key}_vs_{var_y.key}.png"
output_path = OUTPUT_DIR / filename
print(f"→ Trace {var_y.key} en fonction de {var_x.key}{output_path}")
plot_scatter_pair(
df=df,
var_x=var_x,
var_y=var_y,
output_path=output_path,
sample_step=10, # un point sur 10 : ≈ 32k points au lieu de 320k
)
print("✔ Tous les graphiques de nuages de points ont été générés.")
if __name__ == "__main__":
main()

View File

@ -0,0 +1,45 @@
# scripts/plot_correlation_heatmap.py
from __future__ import annotations
from pathlib import Path
from meteo.dataset import load_raw_csv
from meteo.variables import VARIABLES
from meteo.analysis import compute_correlation_matrix_for_variables
from meteo.plots import plot_correlation_heatmap
CSV_PATH = Path("data/weather_minutely.csv")
OUTPUT_PATH = Path("figures/correlation_heatmap.png")
def main() -> None:
if not CSV_PATH.exists():
print(f"⚠ Fichier introuvable : {CSV_PATH}")
print(" Assurez-vous d'avoir généré le dataset minuté.")
return
df = load_raw_csv(CSV_PATH)
print(f"Dataset minuté chargé : {CSV_PATH}")
print(f" Lignes : {len(df)}")
print(f" Colonnes : {list(df.columns)}")
print()
corr = compute_correlation_matrix_for_variables(df, VARIABLES, method="pearson")
print("Matrice de corrélation (aperçu) :")
print(corr)
print()
output_path = plot_correlation_heatmap(
corr=corr,
variables=VARIABLES,
output_path=OUTPUT_PATH,
annotate=True,
)
print(f"✔ Heatmap de corrélation sauvegardée dans : {output_path}")
if __name__ == "__main__":
main()

View File

@ -0,0 +1,69 @@
# scripts/plot_lagged_correlations.py
from __future__ import annotations
from pathlib import Path
from meteo.dataset import load_raw_csv
from meteo.variables import VARIABLES_BY_KEY
from meteo.analysis import compute_lagged_correlation
from meteo.plots import plot_lagged_correlation
CSV_PATH = Path("data/weather_minutely.csv")
OUTPUT_DIR = Path("figures/lagged_correlations")
# Paires à analyser (clé de variable X, clé de variable Y)
# Convention : X précède potentiellement Y
INTERESTING_PAIRS: list[tuple[str, str]] = [
("temperature", "humidity"),
("temperature", "rain_rate"),
("pressure", "rain_rate"),
("pressure", "wind_speed"),
("pressure", "illuminance"),
("illuminance", "temperature"),
("humidity", "rain_rate"),
]
def main() -> None:
if not CSV_PATH.exists():
print(f"⚠ Fichier introuvable : {CSV_PATH}")
return
df = load_raw_csv(CSV_PATH)
print(f"Dataset minuté chargé : {CSV_PATH}")
print(f" Lignes : {len(df)}")
print(f" Colonnes : {list(df.columns)}")
print()
for key_x, key_y in INTERESTING_PAIRS:
var_x = VARIABLES_BY_KEY[key_x]
var_y = VARIABLES_BY_KEY[key_y]
print(f"→ Corrélation décalée : {var_x.key}{var_y.key}")
lag_df = compute_lagged_correlation(
df=df,
var_x=var_x,
var_y=var_y,
max_lag_minutes=360, # ± 6 heures
step_minutes=10, # pas de 10 minutes
method="pearson",
)
filename = f"lagcorr_{var_x.key}_to_{var_y.key}.png"
output_path = OUTPUT_DIR / filename
plot_lagged_correlation(
lag_df=lag_df,
var_x=var_x,
var_y=var_y,
output_path=output_path,
)
print("✔ Graphiques de corrélation décalée générés.")
if __name__ == "__main__":
main()