#!/usr/bin/python3
# -*- coding: utf-8 -*-
########################################################################
#
# This file is part of python module <pyspc>.
# Copyright (C) 2013-2021 R. Marty
# (renaud.marty@developpement-durable.gouv.fr)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see COPYING.txt).
# If not, see <http://www.gnu.org/licenses/>.
#
########################################################################
"""
Régime hydro-météorologique par Sauquet
"""
import numpy as np
import pandas as pnd
import pyspc.core.exception as _exception
REGIMES = pnd.DataFrame({
('0', 'nivo_glaciaire'): [-0.96, -1.08, -0.96, -0.60, 0.36, 1.44,
1.68, 1.32, 0.48, -0.24, -0.60, -0.84],
('1', 'nival'): [-0.84, -0.98, -0.84, -0.14, 1.41, 2.25,
0.98, 0.14, -0.28, -0.42, -0.56, -0.70],
('2', 'nival_transition'): [-0.85, -0.85, -0.64, 0, 1.71, 2.14,
0.85, 0, -0.64, -0.64, -0.43, -0.64],
('3', 'nivo_pluvial'): [-0.69, -0.92, 0.46, 1.61, 2.07, 0.23,
-0.46, -0.92, -1.15, -0.69, 0, 0.46],
('4', 'pluvial_1'): [1.11, 1.18, 1.25, 1.11, 0.34, -0.37,
-0.80, -1.36, -1.36, -1.01, -0.51, 0.41],
('5', 'pluvial_2'): [1.36, 1.17, 0.76, 0.73, -0.07, -0.76,
-1.25, -1.55, -1.14, -0.56, 0.40, 0.92],
('6', 'pluvial_3'): [1.07, 1.40, 0.92, 1.07, 0.52, -0.43,
-1.15, -1.41, -1.24, -0.93, -0.22, 0.42],
('7', 'pluvial_4'): [1.56, 0.99, 0.76, 0.23, -0.45, -0.87,
-1.17, -1.32, -1.02, -0.45, 0.33, 1.14],
('8', 'pluvial_5'): [1.94, 1.28, 0.56, 0.30, -0.38, -0.86,
-1.05, -1.15, -0.97, -0.68, 0.06, 0.96],
('9', 'pluvial_6'): [1.44, 1.40, 0.67, 0.71, 0.05, -0.78,
-1.16, -1.36, -1.16, -0.78, 0.11, 0.86],
('10', 'pluvial_7'): [1.17, 0.18, -0.03, 0.33, 0.08, -0.93,
-1.43, -1.50, -0.99, 0.52, 1.59, 1],
('11', 'pluvial_8'): [0.84, 0.43, 0.52, 1.22, 1.13, -0.33,
-1.39, -1.74, -1.30, -0.48, 0.55, 0.55]},
index=range(1, 13)
)
[docs]
def compute_distance(df):
"""
Définir la similarité du régime hydrologique avec les références Sauquet.
Parameters
----------
df : pandas.DataFrame
Valeurs mensuelles
Returns
-------
norm : pandas.DataFrame
Valeurs mensuelles normalisées
regimes : pandas.DataFrame
Identifiants des colonnes de df, des régimes et critère de similarité
See Also
--------
pyspc.model.sauquet.REGIMES
Examples
--------
>>> import pyspc.model.sauquet as _sauquet
>>> df = pnd.DataFrame(
... {'K2163110': [1.430, 1.540, 1.700, 1.670, 1.320, 0.829,
... 0.380, 0.241, 0.324, 0.613, 1.140, 1.440]},
... index=range(12))
>>> df
K2163110
1 1.430
2 1.540
3 1.700
4 1.670
5 1.320
6 0.829
7 0.380
8 0.241
9 0.324
10 0.613
11 1.140
12 1.440
>>> norm, regimes = _sauquet.compute_distance(df)
>>> norm
K2163110
1 0.690228
2 0.891221
3 1.183574
4 1.128758
5 0.489235
6 -0.407924
7 -1.228341
8 -1.482323
9 -1.330664
10 -0.802601
11 0.160338
12 0.708500
>>> regimes
source id_regime lbl_regime distance
0 K2163110 0 nivo_glaciaire 6.364468
1 K2163110 1 nival 5.542722
2 K2163110 2 nival_transition 5.212776
3 K2163110 3 nivo_pluvial 3.144169
4 K2163110 4 pluvial_1 1.033849
5 K2163110 5 pluvial_2 1.226321
6 K2163110 6 pluvial_3 0.860899
7 K2163110 7 pluvial_4 1.820628
8 K2163110 8 pluvial_5 2.027160
9 K2163110 9 pluvial_6 1.290835
10 K2163110 10 pluvial_7 2.705927
11 K2163110 11 pluvial_8 1.214482
"""
# =====================================================================
# 0- CONTROLES
# =====================================================================
_exception.raise_valueerror(
not isinstance(df, pnd.DataFrame),
"Les valeurs ne sont pas fournies sous forme de DataFrame")
months = list(range(1, 13))
_exception.raise_valueerror(
len(df.index) != len(months)
or not all([x in df.index for x in months]),
"Les valeurs sont incomplètes")
# =====================================================================
# 1- MISE EN FORME DES DONNEES : NORMALISATION
# =====================================================================
norm = (df - df.mean()) / df.std()
# =====================================================================
# 2- CALCUL DES CRITERES DE SIMILARITE PAR REGIME SAUQUET
# =====================================================================
regimes = []
for c in norm.columns:
for kr, vr in REGIMES.items():
d = np.sqrt(np.sum(np.power(
norm[c].to_frame().values.squeeze() - vr.values, 2)))
regimes.append((c, kr[0], kr[1], d))
regimes = pnd.DataFrame.from_records(
regimes, columns=['source', 'id_regime', 'lbl_regime', 'distance'])
regimes['id_regime'] = regimes['id_regime'].astype(np.int64)
return norm, regimes