pynumerics 2.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pynumerics/__init__.py +73 -0
- pynumerics/_bin/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- pynumerics/_bin/Microsoft.CodeAnalysis.LICENSE.txt +27 -0
- pynumerics/_bin/Microsoft.CodeAnalysis.dll +0 -0
- pynumerics/_bin/Numerics.dll +0 -0
- pynumerics/_bin/pynumerics.runtimeconfig.json +15 -0
- pynumerics/_coverage.py +3825 -0
- pynumerics/_util.py +237 -0
- pynumerics/_version.py +40 -0
- pynumerics/bootstrap.py +593 -0
- pynumerics/callbacks.py +791 -0
- pynumerics/copulas.py +910 -0
- pynumerics/data.py +2233 -0
- pynumerics/differentiation.py +348 -0
- pynumerics/distributions.py +4043 -0
- pynumerics/download.py +623 -0
- pynumerics/enums.py +119 -0
- pynumerics/errors.py +245 -0
- pynumerics/functions.py +1142 -0
- pynumerics/goodness_of_fit.py +699 -0
- pynumerics/graphs.py +556 -0
- pynumerics/hypothesis_tests.py +445 -0
- pynumerics/identity.py +144 -0
- pynumerics/integration.py +677 -0
- pynumerics/linalg.py +1408 -0
- pynumerics/machine_learning.py +1335 -0
- pynumerics/marshal.py +733 -0
- pynumerics/mathematics.py +1053 -0
- pynumerics/mcmc.py +1406 -0
- pynumerics/multivariate.py +1539 -0
- pynumerics/ode.py +156 -0
- pynumerics/optimization.py +1736 -0
- pynumerics/probability.py +966 -0
- pynumerics/py.typed +0 -0
- pynumerics/regional.py +522 -0
- pynumerics/roots.py +274 -0
- pynumerics/runtime.py +384 -0
- pynumerics/sampling.py +1758 -0
- pynumerics/special.py +1079 -0
- pynumerics/statistics.py +1958 -0
- pynumerics/timeseries.py +1326 -0
- pynumerics-2.3.0.dist-info/METADATA +142 -0
- pynumerics-2.3.0.dist-info/RECORD +46 -0
- pynumerics-2.3.0.dist-info/WHEEL +5 -0
- pynumerics-2.3.0.dist-info/licenses/LICENSE +10 -0
- pynumerics-2.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,699 @@
|
|
|
1
|
+
"""Goodness-of-fit measures from ``Numerics.Data.Statistics.GoodnessOfFit``.
|
|
2
|
+
|
|
3
|
+
Information criteria (AIC, AICc, BIC and their weights), error metrics (RMSE, MSE, MAE, MAPE,
|
|
4
|
+
sMAPE), hydrologic efficiencies (Nash-Sutcliffe, Kling-Gupta, PBIAS, RSR, the Willmott indices
|
|
5
|
+
of agreement, volumetric efficiency), binary classification scores, and the
|
|
6
|
+
Kolmogorov-Smirnov, Anderson-Darling and chi-squared statistics of a sample against a
|
|
7
|
+
distribution. Each function calls one Numerics member. The paired metrics take the observed
|
|
8
|
+
values first and the modeled values second, as Numerics does.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
from pynumerics._util import cached_overload, namespace
|
|
18
|
+
from pynumerics.errors import translate_public
|
|
19
|
+
from pynumerics.marshal import to_net_doubles, to_net_matrix, to_numpy_doubles
|
|
20
|
+
from pynumerics.statistics import _sorted
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _gof() -> Any:
|
|
24
|
+
"""Return ``Numerics.Data.Statistics.GoodnessOfFit`` after starting the runtime."""
|
|
25
|
+
return namespace("Numerics.Data.Statistics").GoodnessOfFit
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _distribution(model: Any) -> Any:
|
|
29
|
+
"""Return the .NET ``UnivariateDistributionBase`` behind a distribution, or None for anything else."""
|
|
30
|
+
import clr # noqa: PLC0415 - the runtime is running once _gof returns
|
|
31
|
+
|
|
32
|
+
net = getattr(model, "net", model)
|
|
33
|
+
base = clr.GetClrType(namespace("Numerics.Distributions").UnivariateDistributionBase)
|
|
34
|
+
try:
|
|
35
|
+
return net if base.IsInstanceOfType(net) else None
|
|
36
|
+
except TypeError:
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _required_distribution(model: Any) -> Any:
|
|
41
|
+
"""Return the .NET distribution behind ``model``, or raise TypeError."""
|
|
42
|
+
_gof()
|
|
43
|
+
net = _distribution(model)
|
|
44
|
+
if net is None:
|
|
45
|
+
raise TypeError(f"Expected a univariate distribution; got {type(model).__name__}.")
|
|
46
|
+
return net
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _paired(name: str, observed: Any, modeled: Any) -> float:
|
|
50
|
+
"""Call a paired ``GoodnessOfFit`` metric on observed and modeled values."""
|
|
51
|
+
return float(getattr(_gof(), name)(to_net_doubles(observed), to_net_doubles(modeled)))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def aic(number_of_parameters: int, log_likelihood: float) -> float:
|
|
55
|
+
"""Return the Akaike information criterion ``2k - 2 ln L`` (``GoodnessOfFit.AIC``).
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
number_of_parameters : int
|
|
60
|
+
The number of fitted parameters k.
|
|
61
|
+
log_likelihood : float
|
|
62
|
+
The maximized log-likelihood.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
float
|
|
67
|
+
The AIC; lower is preferred.
|
|
68
|
+
"""
|
|
69
|
+
return float(_gof().AIC(int(number_of_parameters), float(log_likelihood)))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def aicc(sample_size: int, number_of_parameters: int, log_likelihood: float) -> float:
|
|
73
|
+
"""Return the small-sample corrected AIC ``AIC + 2k(k + 1) / (n - k - 1)`` (``GoodnessOfFit.AICc``).
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
77
|
+
sample_size : int
|
|
78
|
+
The sample size n.
|
|
79
|
+
number_of_parameters : int
|
|
80
|
+
The number of fitted parameters k.
|
|
81
|
+
log_likelihood : float
|
|
82
|
+
The maximized log-likelihood.
|
|
83
|
+
|
|
84
|
+
Returns
|
|
85
|
+
-------
|
|
86
|
+
float
|
|
87
|
+
The AICc; lower is preferred.
|
|
88
|
+
"""
|
|
89
|
+
return float(_gof().AICc(int(sample_size), int(number_of_parameters), float(log_likelihood)))
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def bic(sample_size: int, number_of_parameters: int, log_likelihood: float) -> float:
|
|
93
|
+
"""Return the Bayesian information criterion ``k ln n - 2 ln L`` (``GoodnessOfFit.BIC``).
|
|
94
|
+
|
|
95
|
+
Parameters
|
|
96
|
+
----------
|
|
97
|
+
sample_size : int
|
|
98
|
+
The sample size n.
|
|
99
|
+
number_of_parameters : int
|
|
100
|
+
The number of fitted parameters k.
|
|
101
|
+
log_likelihood : float
|
|
102
|
+
The maximized log-likelihood.
|
|
103
|
+
|
|
104
|
+
Returns
|
|
105
|
+
-------
|
|
106
|
+
float
|
|
107
|
+
The BIC; lower is preferred.
|
|
108
|
+
"""
|
|
109
|
+
return float(_gof().BIC(int(sample_size), int(number_of_parameters), float(log_likelihood)))
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def aic_weights(aic_values: Any) -> np.ndarray:
|
|
113
|
+
"""Return the Akaike weights of a set of models (``GoodnessOfFit.AICWeights``).
|
|
114
|
+
|
|
115
|
+
Parameters
|
|
116
|
+
----------
|
|
117
|
+
aic_values : array_like
|
|
118
|
+
One AIC per model.
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
numpy.ndarray
|
|
123
|
+
``exp(-(AIC_i - AIC_min) / 2)`` normalized to sum to one.
|
|
124
|
+
"""
|
|
125
|
+
return to_numpy_doubles(_gof().AICWeights(to_net_doubles(aic_values)))
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def rmse(observed: Any, model: Any, k: int = 0, plotting_positions: Any = None) -> float:
|
|
129
|
+
"""Return the root mean square error (``GoodnessOfFit.RMSE``).
|
|
130
|
+
|
|
131
|
+
With modeled values, ``sqrt(sum (m - o)^2 / (n - k))``. With a distribution, the observed
|
|
132
|
+
values are compared with its quantiles at ``plotting_positions`` (Weibull positions of the
|
|
133
|
+
sorted observations by default), and k is the distribution's parameter count.
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
observed : array_like
|
|
138
|
+
The observed values.
|
|
139
|
+
model : array_like or UnivariateDistribution
|
|
140
|
+
The modeled values, one per observation, or a fitted distribution.
|
|
141
|
+
k : int, optional
|
|
142
|
+
The number of fitted parameters for modeled values; default 0. Ignored for a distribution.
|
|
143
|
+
plotting_positions : array_like, optional
|
|
144
|
+
The non-exceedance probabilities of the observations, in their order, for a distribution.
|
|
145
|
+
|
|
146
|
+
Returns
|
|
147
|
+
-------
|
|
148
|
+
float
|
|
149
|
+
The RMSE.
|
|
150
|
+
|
|
151
|
+
Raises
|
|
152
|
+
------
|
|
153
|
+
ValueError
|
|
154
|
+
If the lengths differ or ``k`` is not in [0, n).
|
|
155
|
+
"""
|
|
156
|
+
gof = _gof()
|
|
157
|
+
net = _distribution(model)
|
|
158
|
+
if net is None:
|
|
159
|
+
if plotting_positions is not None:
|
|
160
|
+
raise ValueError("plotting_positions applies only when model is a distribution.")
|
|
161
|
+
return float(gof.RMSE(to_net_doubles(observed), to_net_doubles(model), int(k)))
|
|
162
|
+
if plotting_positions is None:
|
|
163
|
+
return float(gof.RMSE(to_net_doubles(observed), net))
|
|
164
|
+
return float(gof.RMSE(to_net_doubles(observed), to_net_doubles(plotting_positions), net))
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def rmse_weights(rmse_values: Any) -> np.ndarray:
|
|
168
|
+
"""Return inverse-MSE model weights (``GoodnessOfFit.RMSEWeights``).
|
|
169
|
+
|
|
170
|
+
Parameters
|
|
171
|
+
----------
|
|
172
|
+
rmse_values : array_like
|
|
173
|
+
One RMSE per model.
|
|
174
|
+
|
|
175
|
+
Returns
|
|
176
|
+
-------
|
|
177
|
+
numpy.ndarray
|
|
178
|
+
``RMSE_i^-2`` normalized to sum to one.
|
|
179
|
+
"""
|
|
180
|
+
return to_numpy_doubles(_gof().RMSEWeights(to_net_doubles(rmse_values)))
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def mse(observed: Any, modeled: Any) -> float:
|
|
184
|
+
"""Return the mean squared error (``GoodnessOfFit.MSE``).
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
observed, modeled : array_like
|
|
189
|
+
Observed and modeled values of the same length.
|
|
190
|
+
|
|
191
|
+
Returns
|
|
192
|
+
-------
|
|
193
|
+
float
|
|
194
|
+
The MSE.
|
|
195
|
+
"""
|
|
196
|
+
return _paired("MSE", observed, modeled)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def mae(observed: Any, modeled: Any) -> float:
|
|
200
|
+
"""Return the mean absolute error (``GoodnessOfFit.MAE``).
|
|
201
|
+
|
|
202
|
+
Parameters
|
|
203
|
+
----------
|
|
204
|
+
observed, modeled : array_like
|
|
205
|
+
Observed and modeled values of the same length.
|
|
206
|
+
|
|
207
|
+
Returns
|
|
208
|
+
-------
|
|
209
|
+
float
|
|
210
|
+
The MAE.
|
|
211
|
+
"""
|
|
212
|
+
return _paired("MAE", observed, modeled)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def mape(observed: Any, modeled: Any) -> float:
|
|
216
|
+
"""Return the mean absolute percentage error ``100/n sum |o - m| / |o|`` (``GoodnessOfFit.MAPE``).
|
|
217
|
+
|
|
218
|
+
Parameters
|
|
219
|
+
----------
|
|
220
|
+
observed, modeled : array_like
|
|
221
|
+
Observed and modeled values of the same length.
|
|
222
|
+
|
|
223
|
+
Returns
|
|
224
|
+
-------
|
|
225
|
+
float
|
|
226
|
+
The MAPE in percent.
|
|
227
|
+
"""
|
|
228
|
+
return _paired("MAPE", observed, modeled)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def smape(observed: Any, modeled: Any) -> float:
|
|
232
|
+
"""Return the symmetric MAPE ``100/n sum 2|o - m| / (|o| + |m|)`` (``GoodnessOfFit.sMAPE``).
|
|
233
|
+
|
|
234
|
+
Parameters
|
|
235
|
+
----------
|
|
236
|
+
observed, modeled : array_like
|
|
237
|
+
Observed and modeled values of the same length.
|
|
238
|
+
|
|
239
|
+
Returns
|
|
240
|
+
-------
|
|
241
|
+
float
|
|
242
|
+
The sMAPE in percent, in [0, 200].
|
|
243
|
+
"""
|
|
244
|
+
return _paired("sMAPE", observed, modeled)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def nash_sutcliffe_efficiency(observed: Any, modeled: Any) -> float:
|
|
248
|
+
"""Return the Nash-Sutcliffe efficiency ``1 - sum (o - m)^2 / sum (o - mean o)^2`` (``NashSutcliffeEfficiency``).
|
|
249
|
+
|
|
250
|
+
Parameters
|
|
251
|
+
----------
|
|
252
|
+
observed, modeled : array_like
|
|
253
|
+
Observed and modeled values of the same length.
|
|
254
|
+
|
|
255
|
+
Returns
|
|
256
|
+
-------
|
|
257
|
+
float
|
|
258
|
+
The NSE, at most one.
|
|
259
|
+
"""
|
|
260
|
+
return _paired("NashSutcliffeEfficiency", observed, modeled)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def log_nash_sutcliffe_efficiency(observed: Any, modeled: Any, epsilon: float | None = None) -> float:
|
|
264
|
+
"""Return the Nash-Sutcliffe efficiency of ``ln(x + epsilon)`` (``GoodnessOfFit.LogNashSutcliffeEfficiency``).
|
|
265
|
+
|
|
266
|
+
Parameters
|
|
267
|
+
----------
|
|
268
|
+
observed, modeled : array_like
|
|
269
|
+
Observed and modeled values of the same length.
|
|
270
|
+
epsilon : float, optional
|
|
271
|
+
The non-negative offset; default the observed mean over 100 (Pushpalatha et al., 2012).
|
|
272
|
+
|
|
273
|
+
Returns
|
|
274
|
+
-------
|
|
275
|
+
float
|
|
276
|
+
The log NSE.
|
|
277
|
+
"""
|
|
278
|
+
eps = -1.0 if epsilon is None else float(epsilon)
|
|
279
|
+
return float(_gof().LogNashSutcliffeEfficiency(to_net_doubles(observed), to_net_doubles(modeled), eps))
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def kling_gupta_efficiency(observed: Any, modeled: Any) -> float:
|
|
283
|
+
"""Return the Kling-Gupta efficiency of Gupta et al. (2009) (``GoodnessOfFit.KlingGuptaEfficiency``).
|
|
284
|
+
|
|
285
|
+
``1 - sqrt((r - 1)^2 + (alpha - 1)^2 + (beta - 1)^2)`` with r the Pearson correlation,
|
|
286
|
+
alpha the ratio of standard deviations and beta the ratio of means (modeled over observed).
|
|
287
|
+
|
|
288
|
+
Parameters
|
|
289
|
+
----------
|
|
290
|
+
observed, modeled : array_like
|
|
291
|
+
Observed and modeled values of the same length.
|
|
292
|
+
|
|
293
|
+
Returns
|
|
294
|
+
-------
|
|
295
|
+
float
|
|
296
|
+
The KGE; -10 when either series is constant, NaN for a single pair.
|
|
297
|
+
"""
|
|
298
|
+
return _paired("KlingGuptaEfficiency", observed, modeled)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def kling_gupta_efficiency_mod(observed: Any, modeled: Any) -> float:
|
|
302
|
+
"""Return the modified Kling-Gupta efficiency of Kling et al. (2012) (``GoodnessOfFit.KlingGuptaEfficiencyMod``).
|
|
303
|
+
|
|
304
|
+
As :func:`kling_gupta_efficiency` with alpha replaced by the ratio of coefficients of variation.
|
|
305
|
+
|
|
306
|
+
Parameters
|
|
307
|
+
----------
|
|
308
|
+
observed, modeled : array_like
|
|
309
|
+
Observed and modeled values of the same length.
|
|
310
|
+
|
|
311
|
+
Returns
|
|
312
|
+
-------
|
|
313
|
+
float
|
|
314
|
+
The KGE'; -10 when either series is constant, NaN for a single pair.
|
|
315
|
+
"""
|
|
316
|
+
return _paired("KlingGuptaEfficiencyMod", observed, modeled)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def pbias(observed: Any, modeled: Any) -> float:
|
|
320
|
+
"""Return the percent bias ``100 sum (o - m) / sum o`` of Moriasi et al. (2007) (``GoodnessOfFit.PBIAS``).
|
|
321
|
+
|
|
322
|
+
Parameters
|
|
323
|
+
----------
|
|
324
|
+
observed, modeled : array_like
|
|
325
|
+
Observed and modeled values of the same length.
|
|
326
|
+
|
|
327
|
+
Returns
|
|
328
|
+
-------
|
|
329
|
+
float
|
|
330
|
+
The PBIAS in percent; positive when the model underestimates the observed total and negative
|
|
331
|
+
when it overestimates. R's hydroGOF ``pbias`` reports the opposite sign.
|
|
332
|
+
"""
|
|
333
|
+
return _paired("PBIAS", observed, modeled)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def rsr(observed: Any, modeled: Any) -> float:
|
|
337
|
+
"""Return ``sqrt(sum (o - m)^2 / sum (o - mean o)^2)``, the RMSE over the observed spread (``GoodnessOfFit.RSR``).
|
|
338
|
+
|
|
339
|
+
Parameters
|
|
340
|
+
----------
|
|
341
|
+
observed, modeled : array_like
|
|
342
|
+
Observed and modeled values of the same length.
|
|
343
|
+
|
|
344
|
+
Returns
|
|
345
|
+
-------
|
|
346
|
+
float
|
|
347
|
+
The RSR, zero for a perfect model.
|
|
348
|
+
"""
|
|
349
|
+
return _paired("RSR", observed, modeled)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def r_squared(observed: Any, modeled: Any) -> float:
|
|
353
|
+
"""Return the coefficient of determination, the squared Pearson correlation (``GoodnessOfFit.RSquared``).
|
|
354
|
+
|
|
355
|
+
Parameters
|
|
356
|
+
----------
|
|
357
|
+
observed, modeled : array_like
|
|
358
|
+
Observed and modeled values of the same length.
|
|
359
|
+
|
|
360
|
+
Returns
|
|
361
|
+
-------
|
|
362
|
+
float
|
|
363
|
+
R squared, in [0, 1].
|
|
364
|
+
"""
|
|
365
|
+
return _paired("RSquared", observed, modeled)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def index_of_agreement(observed: Any, modeled: Any) -> float:
|
|
369
|
+
"""Return Willmott's (1981) index of agreement d (``GoodnessOfFit.IndexOfAgreement``).
|
|
370
|
+
|
|
371
|
+
``1 - sum (m - o)^2 / sum (|m - mean o| + |o - mean o|)^2``.
|
|
372
|
+
|
|
373
|
+
Parameters
|
|
374
|
+
----------
|
|
375
|
+
observed, modeled : array_like
|
|
376
|
+
Observed and modeled values of the same length.
|
|
377
|
+
|
|
378
|
+
Returns
|
|
379
|
+
-------
|
|
380
|
+
float
|
|
381
|
+
The index d, in [0, 1].
|
|
382
|
+
"""
|
|
383
|
+
return _paired("IndexOfAgreement", observed, modeled)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def modified_index_of_agreement(observed: Any, modeled: Any) -> float:
|
|
387
|
+
"""Return the modified index of agreement d1 of Willmott et al. (1985) (``ModifiedIndexOfAgreement``).
|
|
388
|
+
|
|
389
|
+
``1 - sum |m - o| / sum (|m - mean o| + |o - mean o|)``.
|
|
390
|
+
|
|
391
|
+
Parameters
|
|
392
|
+
----------
|
|
393
|
+
observed, modeled : array_like
|
|
394
|
+
Observed and modeled values of the same length.
|
|
395
|
+
|
|
396
|
+
Returns
|
|
397
|
+
-------
|
|
398
|
+
float
|
|
399
|
+
The index d1, in [0, 1].
|
|
400
|
+
"""
|
|
401
|
+
return _paired("ModifiedIndexOfAgreement", observed, modeled)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def refined_index_of_agreement(observed: Any, modeled: Any) -> float:
|
|
405
|
+
"""Return the refined index of agreement dr of Willmott et al. (2012) (``RefinedIndexOfAgreement``).
|
|
406
|
+
|
|
407
|
+
Parameters
|
|
408
|
+
----------
|
|
409
|
+
observed, modeled : array_like
|
|
410
|
+
Observed and modeled values of the same length.
|
|
411
|
+
|
|
412
|
+
Returns
|
|
413
|
+
-------
|
|
414
|
+
float
|
|
415
|
+
The index dr, in [-1, 1].
|
|
416
|
+
"""
|
|
417
|
+
return _paired("RefinedIndexOfAgreement", observed, modeled)
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
def volumetric_efficiency(observed: Any, modeled: Any) -> float:
|
|
421
|
+
"""Return the volumetric efficiency ``1 - sum |m - o| / sum |o|`` of Criss and Winston (2008).
|
|
422
|
+
|
|
423
|
+
Calls ``GoodnessOfFit.VolumetricEfficiency``.
|
|
424
|
+
|
|
425
|
+
Parameters
|
|
426
|
+
----------
|
|
427
|
+
observed, modeled : array_like
|
|
428
|
+
Observed and modeled values of the same length.
|
|
429
|
+
|
|
430
|
+
Returns
|
|
431
|
+
-------
|
|
432
|
+
float
|
|
433
|
+
VE, at most one.
|
|
434
|
+
"""
|
|
435
|
+
return _paired("VolumetricEfficiency", observed, modeled)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def accuracy(observed: Any, modeled: Any) -> float:
|
|
439
|
+
"""Return the percentage of exact matches (``GoodnessOfFit.Accuracy``).
|
|
440
|
+
|
|
441
|
+
Parameters
|
|
442
|
+
----------
|
|
443
|
+
observed, modeled : array_like
|
|
444
|
+
Observed and modeled labels of the same length.
|
|
445
|
+
|
|
446
|
+
Returns
|
|
447
|
+
-------
|
|
448
|
+
float
|
|
449
|
+
The accuracy in percent.
|
|
450
|
+
"""
|
|
451
|
+
return _paired("Accuracy", observed, modeled)
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def precision(observed: Any, modeled: Any) -> float:
|
|
455
|
+
"""Return the precision ``TP / (TP + FP)`` of binary labels (``GoodnessOfFit.Precision``).
|
|
456
|
+
|
|
457
|
+
Parameters
|
|
458
|
+
----------
|
|
459
|
+
observed, modeled : array_like
|
|
460
|
+
Observed and modeled 0/1 labels of the same length.
|
|
461
|
+
|
|
462
|
+
Returns
|
|
463
|
+
-------
|
|
464
|
+
float
|
|
465
|
+
The precision, in [0, 1].
|
|
466
|
+
"""
|
|
467
|
+
return _paired("Precision", observed, modeled)
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def recall(observed: Any, modeled: Any) -> float:
|
|
471
|
+
"""Return the recall ``TP / (TP + FN)`` of binary labels (``GoodnessOfFit.Recall``).
|
|
472
|
+
|
|
473
|
+
Parameters
|
|
474
|
+
----------
|
|
475
|
+
observed, modeled : array_like
|
|
476
|
+
Observed and modeled 0/1 labels of the same length.
|
|
477
|
+
|
|
478
|
+
Returns
|
|
479
|
+
-------
|
|
480
|
+
float
|
|
481
|
+
The recall, in [0, 1].
|
|
482
|
+
"""
|
|
483
|
+
return _paired("Recall", observed, modeled)
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
def f1_score(observed: Any, modeled: Any) -> float:
|
|
487
|
+
"""Return the F1 score ``2TP / (2TP + FP + FN)`` of binary labels (``GoodnessOfFit.F1Score``).
|
|
488
|
+
|
|
489
|
+
Parameters
|
|
490
|
+
----------
|
|
491
|
+
observed, modeled : array_like
|
|
492
|
+
Observed and modeled 0/1 labels of the same length.
|
|
493
|
+
|
|
494
|
+
Returns
|
|
495
|
+
-------
|
|
496
|
+
float
|
|
497
|
+
The F1 score, in [0, 1].
|
|
498
|
+
"""
|
|
499
|
+
return _paired("F1Score", observed, modeled)
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def specificity(observed: Any, modeled: Any) -> float:
|
|
503
|
+
"""Return the specificity ``TN / (TN + FP)`` of binary labels (``GoodnessOfFit.Specificity``).
|
|
504
|
+
|
|
505
|
+
Parameters
|
|
506
|
+
----------
|
|
507
|
+
observed, modeled : array_like
|
|
508
|
+
Observed and modeled 0/1 labels of the same length.
|
|
509
|
+
|
|
510
|
+
Returns
|
|
511
|
+
-------
|
|
512
|
+
float
|
|
513
|
+
The specificity, in [0, 1].
|
|
514
|
+
"""
|
|
515
|
+
return _paired("Specificity", observed, modeled)
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def balanced_accuracy(observed: Any, modeled: Any) -> float:
|
|
519
|
+
"""Return the mean of recall and specificity of binary labels (``GoodnessOfFit.BalancedAccuracy``).
|
|
520
|
+
|
|
521
|
+
Parameters
|
|
522
|
+
----------
|
|
523
|
+
observed, modeled : array_like
|
|
524
|
+
Observed and modeled 0/1 labels of the same length.
|
|
525
|
+
|
|
526
|
+
Returns
|
|
527
|
+
-------
|
|
528
|
+
float
|
|
529
|
+
The balanced accuracy, in [0, 1].
|
|
530
|
+
"""
|
|
531
|
+
return _paired("BalancedAccuracy", observed, modeled)
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
def _column_uniform(member: str, sorted_samples: Any) -> np.ndarray:
|
|
535
|
+
"""Call a batched ``GoodnessOfFit`` statistic against Uniform(0, 1) on one sample per column.
|
|
536
|
+
|
|
537
|
+
The matrix crosses in one copy, and the member is looked up on first use only.
|
|
538
|
+
"""
|
|
539
|
+
bound = cached_overload(f"GoodnessOfFit.{member}(double[,])", lambda: getattr(_gof(), member))
|
|
540
|
+
return to_numpy_doubles(bound(to_net_matrix(sorted_samples)))
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
def column_kolmogorov_smirnov_uniform(sorted_samples: Any) -> np.ndarray:
|
|
544
|
+
"""Return the Kolmogorov-Smirnov D of each column against Uniform(0, 1).
|
|
545
|
+
|
|
546
|
+
Wraps ``GoodnessOfFit.ColumnKolmogorovSmirnovUniform``.
|
|
547
|
+
|
|
548
|
+
Each value is bitwise :func:`kolmogorov_smirnov` of the column against ``Uniform(0, 1)``, as
|
|
549
|
+
``scipy.stats.kstest(u, "uniform").statistic``, for all columns in one call.
|
|
550
|
+
|
|
551
|
+
Parameters
|
|
552
|
+
----------
|
|
553
|
+
sorted_samples : array_like
|
|
554
|
+
An (n, m) array holding m samples of n values, one per column, each ascending, in [0, 1].
|
|
555
|
+
|
|
556
|
+
Returns
|
|
557
|
+
-------
|
|
558
|
+
numpy.ndarray
|
|
559
|
+
One statistic per column.
|
|
560
|
+
|
|
561
|
+
Raises
|
|
562
|
+
------
|
|
563
|
+
ValueError
|
|
564
|
+
If there are no rows, or a value is NaN or outside [0, 1], or a column is not ascending.
|
|
565
|
+
"""
|
|
566
|
+
return _column_uniform("ColumnKolmogorovSmirnovUniform", sorted_samples)
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
def column_anderson_darling_uniform(sorted_samples: Any) -> np.ndarray:
|
|
570
|
+
"""Return the Anderson-Darling A^2 of each column against Uniform(0, 1).
|
|
571
|
+
|
|
572
|
+
Wraps ``GoodnessOfFit.ColumnAndersonDarlingUniform``.
|
|
573
|
+
|
|
574
|
+
``A^2 = -n - n^-1 sum_i (2i - 1)(ln u_(i) + ln(1 - u_(n+1-i)))`` for each column, bitwise
|
|
575
|
+
:func:`anderson_darling` against ``Uniform(0, 1)``, for all columns in one call. A column with a
|
|
576
|
+
value at 0 or 1 gives infinity.
|
|
577
|
+
|
|
578
|
+
Parameters
|
|
579
|
+
----------
|
|
580
|
+
sorted_samples : array_like
|
|
581
|
+
An (n, m) array holding m samples of n values, one per column, each ascending, in [0, 1].
|
|
582
|
+
|
|
583
|
+
Returns
|
|
584
|
+
-------
|
|
585
|
+
numpy.ndarray
|
|
586
|
+
One statistic per column.
|
|
587
|
+
|
|
588
|
+
Raises
|
|
589
|
+
------
|
|
590
|
+
ValueError
|
|
591
|
+
If there are no rows, or a value is NaN or outside [0, 1], or a column is not ascending.
|
|
592
|
+
"""
|
|
593
|
+
return _column_uniform("ColumnAndersonDarlingUniform", sorted_samples)
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
def kolmogorov_smirnov(sample: Any, distribution: Any, data_is_sorted: bool = False) -> float:
|
|
597
|
+
"""Return the one-sample Kolmogorov-Smirnov statistic against a distribution (``GoodnessOfFit.KolmogorovSmirnov``).
|
|
598
|
+
|
|
599
|
+
``D = max_i max(F(x_(i)) - (i - 1)/n, i/n - F(x_(i)))``, as ``scipy.stats.kstest(...).statistic``.
|
|
600
|
+
Unless ``data_is_sorted`` is True the sample is sorted first.
|
|
601
|
+
|
|
602
|
+
Parameters
|
|
603
|
+
----------
|
|
604
|
+
sample : array_like
|
|
605
|
+
The observations.
|
|
606
|
+
distribution : UnivariateDistribution
|
|
607
|
+
The hypothesized distribution.
|
|
608
|
+
data_is_sorted : bool, optional
|
|
609
|
+
Whether ``sample`` is already ascending, which skips the sort; default False.
|
|
610
|
+
|
|
611
|
+
Returns
|
|
612
|
+
-------
|
|
613
|
+
float
|
|
614
|
+
The statistic D.
|
|
615
|
+
|
|
616
|
+
Raises
|
|
617
|
+
------
|
|
618
|
+
TypeError
|
|
619
|
+
If ``distribution`` is not a univariate distribution.
|
|
620
|
+
ValueError
|
|
621
|
+
If the sample is empty.
|
|
622
|
+
"""
|
|
623
|
+
net = _required_distribution(distribution)
|
|
624
|
+
return float(_gof().KolmogorovSmirnov(_sorted(sample, data_is_sorted), net, True))
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
def anderson_darling(sample: Any, distribution: Any, data_is_sorted: bool = False) -> float:
|
|
628
|
+
"""Return the Anderson-Darling statistic against a distribution (``GoodnessOfFit.AndersonDarling``).
|
|
629
|
+
|
|
630
|
+
``A^2 = -n - (1/n) sum (2i - 1) (ln F(x_(i)) + ln(1 - F(x_(n+1-i))))`` with the distribution's
|
|
631
|
+
log CDF and log survival function. Unless ``data_is_sorted`` is True the sample is sorted first.
|
|
632
|
+
|
|
633
|
+
Parameters
|
|
634
|
+
----------
|
|
635
|
+
sample : array_like
|
|
636
|
+
The observations.
|
|
637
|
+
distribution : UnivariateDistribution
|
|
638
|
+
The hypothesized distribution.
|
|
639
|
+
data_is_sorted : bool, optional
|
|
640
|
+
Whether ``sample`` is already ascending, which skips the sort; default False.
|
|
641
|
+
|
|
642
|
+
Returns
|
|
643
|
+
-------
|
|
644
|
+
float
|
|
645
|
+
The statistic A squared.
|
|
646
|
+
|
|
647
|
+
Raises
|
|
648
|
+
------
|
|
649
|
+
TypeError
|
|
650
|
+
If ``distribution`` is not a univariate distribution.
|
|
651
|
+
ValueError
|
|
652
|
+
If the sample is empty.
|
|
653
|
+
"""
|
|
654
|
+
net = _required_distribution(distribution)
|
|
655
|
+
return float(_gof().AndersonDarling(_sorted(sample, data_is_sorted), net, True))
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
def chi_squared(sample: Any, distribution: Any, data_is_sorted: bool = False) -> float:
|
|
659
|
+
"""Return the chi-squared statistic against a distribution (``GoodnessOfFit.ChiSquared``).
|
|
660
|
+
|
|
661
|
+
The sample is binned with the default :class:`pynumerics.statistics.Histogram`, and the
|
|
662
|
+
statistic is ``sum (O_j - E_j)^2 / E_j`` with ``E_j = n (F(upper_j) - F(lower_j))``. Unless
|
|
663
|
+
``data_is_sorted`` is True the sample is sorted first.
|
|
664
|
+
|
|
665
|
+
Parameters
|
|
666
|
+
----------
|
|
667
|
+
sample : array_like
|
|
668
|
+
The observations.
|
|
669
|
+
distribution : UnivariateDistribution
|
|
670
|
+
The hypothesized distribution.
|
|
671
|
+
data_is_sorted : bool, optional
|
|
672
|
+
Whether ``sample`` is already ascending, which skips the sort; default False.
|
|
673
|
+
|
|
674
|
+
Returns
|
|
675
|
+
-------
|
|
676
|
+
float
|
|
677
|
+
The statistic.
|
|
678
|
+
|
|
679
|
+
Raises
|
|
680
|
+
------
|
|
681
|
+
TypeError
|
|
682
|
+
If ``distribution`` is not a univariate distribution.
|
|
683
|
+
ValueError
|
|
684
|
+
If the sample is empty.
|
|
685
|
+
"""
|
|
686
|
+
net = _required_distribution(distribution)
|
|
687
|
+
return float(_gof().ChiSquared(_sorted(sample, data_is_sorted), net))
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
__all__ = [
|
|
691
|
+
"accuracy", "aic", "aic_weights", "aicc", "anderson_darling", "balanced_accuracy", "bic", "chi_squared",
|
|
692
|
+
"column_anderson_darling_uniform", "column_kolmogorov_smirnov_uniform",
|
|
693
|
+
"f1_score", "index_of_agreement", "kling_gupta_efficiency", "kling_gupta_efficiency_mod", "kolmogorov_smirnov",
|
|
694
|
+
"log_nash_sutcliffe_efficiency", "mae", "mape", "modified_index_of_agreement", "mse", "nash_sutcliffe_efficiency",
|
|
695
|
+
"pbias", "precision", "r_squared", "recall", "refined_index_of_agreement", "rmse", "rmse_weights", "rsr",
|
|
696
|
+
"smape", "specificity", "volumetric_efficiency",
|
|
697
|
+
]
|
|
698
|
+
|
|
699
|
+
translate_public(globals())
|