funcsim 0.2.7__tar.gz → 0.2.8__tar.gz
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.
- {funcsim-0.2.7/funcsim.egg-info → funcsim-0.2.8}/PKG-INFO +1 -1
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/__init__.py +2 -2
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/dependence.py +73 -14
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/kde.py +22 -1
- {funcsim-0.2.7 → funcsim-0.2.8/funcsim.egg-info}/PKG-INFO +1 -1
- {funcsim-0.2.7 → funcsim-0.2.8}/setup.py +1 -1
- {funcsim-0.2.7 → funcsim-0.2.8}/LICENSE +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/MANIFEST.in +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/README.md +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/addist.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/conversions.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/copcompare.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/copfit.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/core.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/cpt.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/cvmdist.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/distfit.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/ecdfgof.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/edf.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/eut.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/imanconover.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/ksdist.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/multicore.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/nearby.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/plotting.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/rdarrays.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/screen.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/shapiro.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/shrinkage.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/testsim.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/utests.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim/vect.py +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim.egg-info/SOURCES.txt +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim.egg-info/dependency_links.txt +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim.egg-info/requires.txt +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/funcsim.egg-info/top_level.txt +0 -0
- {funcsim-0.2.7 → funcsim-0.2.8}/setup.cfg +0 -0
|
@@ -324,17 +324,44 @@ class MvKde():
|
|
|
324
324
|
in rows.
|
|
325
325
|
bw : str or ArrayLike, optional
|
|
326
326
|
Bandwidth selection method ('scott' or 'silverman'), or a K-by-K
|
|
327
|
-
bandwidth covariance matrix in the units of the data
|
|
328
|
-
|
|
327
|
+
bandwidth covariance matrix in the units of the data, given as
|
|
328
|
+
anything :func:`numpy.asarray` accepts (a nested list, a NumPy
|
|
329
|
+
array, or a DataFrame). Default is 'scott'. The matrix in use is
|
|
330
|
+
available as :attr:`bandwidth`.
|
|
329
331
|
|
|
330
332
|
Notes
|
|
331
333
|
-----
|
|
332
334
|
Each call to :meth:`draw` consumes K + 1 values from ``ugen``, where K
|
|
333
335
|
is the number of variables.
|
|
336
|
+
|
|
337
|
+
Both rules of thumb give a diagonal bandwidth matrix whose entries are
|
|
338
|
+
a common factor times the variance of each variable, with M
|
|
339
|
+
observations and K variables:
|
|
340
|
+
|
|
341
|
+
- Scott's rule: ``H = M ** (-2 / (K + 4)) * diag(s_1 ** 2, ..., s_K ** 2)``
|
|
342
|
+
- Silverman's rule:
|
|
343
|
+
``H = ((K + 2) * M / 4) ** (-2 / (K + 4)) * diag(s_1 ** 2, ..., s_K ** 2)``
|
|
344
|
+
|
|
345
|
+
where ``s_k`` is the standard deviation of variable k, computed with
|
|
346
|
+
``ddof=0`` (dividing by M). The two rules coincide when K = 2. These
|
|
347
|
+
are the normal-reference rules of Scott (1992, eq. 6.42) and Silverman
|
|
348
|
+
(1986, eq. 4.14), and the same expressions as
|
|
349
|
+
:class:`scipy.stats.gaussian_kde`'s ``scotts_factor`` and
|
|
350
|
+
``silverman_factor``. Before version 0.2.8 the Silverman factor was
|
|
351
|
+
computed as ``(4 * M / (K + 2)) ** (-1 / (K + 4))``, which is correct
|
|
352
|
+
only at K = 2.
|
|
353
|
+
|
|
354
|
+
References
|
|
355
|
+
----------
|
|
356
|
+
Scott, D.W. (1992). Multivariate Density Estimation: Theory, Practice,
|
|
357
|
+
and Visualization. John Wiley & Sons.
|
|
358
|
+
|
|
359
|
+
Silverman, B.W. (1986). Density Estimation for Statistics and Data
|
|
360
|
+
Analysis. Chapman and Hall.
|
|
334
361
|
"""
|
|
335
362
|
def __init__(self,
|
|
336
363
|
data: conversions.ArrayLike,
|
|
337
|
-
bw: str = 'scott'
|
|
364
|
+
bw: Union[str, conversions.ArrayLike, None] = 'scott'
|
|
338
365
|
) -> None:
|
|
339
366
|
self._data = conversions.alToArray(data)
|
|
340
367
|
self._names = conversions.alColNames(data)
|
|
@@ -352,18 +379,27 @@ class MvKde():
|
|
|
352
379
|
mult = self._M**(-1.0/(self._K+4.0))
|
|
353
380
|
self._scott = np.square(mult * np.diagflat(stdevs))
|
|
354
381
|
|
|
355
|
-
# rule-of-thumb silverman bandwidth
|
|
356
|
-
|
|
382
|
+
# rule-of-thumb silverman bandwidth (Silverman, 1986, eq. 4.14;
|
|
383
|
+
# the same expression as scipy's gaussian_kde.silverman_factor).
|
|
384
|
+
# Before 0.2.8 the (K + 2) / 4 factor was inverted, which agrees
|
|
385
|
+
# with this only at K = 2
|
|
386
|
+
smult = ((self._K+2.0) * self._M / 4.0)**(-1.0 / (self._K+4.0))
|
|
357
387
|
self._silverman = np.square(smult * np.diagflat(stdevs))
|
|
358
388
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
389
|
+
# dispatch on the type of bw before comparing it with anything: a
|
|
390
|
+
# NumPy array compared with a string evaluates elementwise under
|
|
391
|
+
# NumPy 2, and its truth value is ambiguous
|
|
392
|
+
if bw is None:
|
|
393
|
+
bw = 'scott'
|
|
394
|
+
if isinstance(bw, str):
|
|
395
|
+
if bw == 'scott':
|
|
396
|
+
self._bw = self._scott
|
|
397
|
+
elif bw == 'silverman':
|
|
398
|
+
self._bw = self._silverman
|
|
399
|
+
else:
|
|
400
|
+
raise ValueError(f"unknown bandwidth method '{bw}'; "
|
|
401
|
+
f"expected 'scott', 'silverman', or a "
|
|
402
|
+
f"{self._K}-by-{self._K} bandwidth matrix")
|
|
367
403
|
else:
|
|
368
404
|
H = np.asarray(bw, dtype=float)
|
|
369
405
|
if H.shape != (self._K, self._K):
|
|
@@ -373,9 +409,32 @@ class MvKde():
|
|
|
373
409
|
Dinv = np.diag(1.0 / self._stds)
|
|
374
410
|
self._bw = Dinv @ H @ Dinv
|
|
375
411
|
|
|
412
|
+
# a bandwidth matrix that is not positive definite is repaired to
|
|
413
|
+
# the nearest one, and the repaired matrix is the one reported by
|
|
414
|
+
# the bandwidth property (nearestpd returns a positive definite
|
|
415
|
+
# input unchanged)
|
|
416
|
+
self._bw = nearby.nearestpd(self._bw)
|
|
417
|
+
|
|
376
418
|
# cholesky decomp of the bandwidth (covariance) matrix, so that
|
|
377
419
|
# draws apply covariance H (not H @ H.T)
|
|
378
|
-
self._chol = np.linalg.cholesky(
|
|
420
|
+
self._chol = np.linalg.cholesky(self._bw)
|
|
421
|
+
|
|
422
|
+
@property
|
|
423
|
+
def bandwidth(self) -> pd.DataFrame:
|
|
424
|
+
"""
|
|
425
|
+
The bandwidth matrix ``H`` in use, in the units of the data, as a
|
|
426
|
+
K-by-K covariance DataFrame whose index and columns are the
|
|
427
|
+
variable names.
|
|
428
|
+
|
|
429
|
+
For ``bw='scott'`` or ``bw='silverman'`` this is diagonal, the
|
|
430
|
+
rule's factor squared times the variance of each variable with
|
|
431
|
+
``ddof=0`` (see the class notes); for a user-supplied matrix it is
|
|
432
|
+
that matrix, or the nearest positive definite matrix to it if it
|
|
433
|
+
was not positive definite.
|
|
434
|
+
"""
|
|
435
|
+
D = np.diag(self._stds)
|
|
436
|
+
return pd.DataFrame(D @ self._bw @ D, index=self._names,
|
|
437
|
+
columns=self._names)
|
|
379
438
|
|
|
380
439
|
def draw(self,
|
|
381
440
|
ugen: Generator[float, None, None]
|
|
@@ -69,7 +69,8 @@ class Kde():
|
|
|
69
69
|
Bandwidth selection method ('scott', 'silverman') or a positive
|
|
70
70
|
float to use as the bandwidth (the standard deviation of the
|
|
71
71
|
Gaussian kernel), in the same units as the data.
|
|
72
|
-
Default is 'scott'.
|
|
72
|
+
Default is 'scott'. The bandwidth in use is available as
|
|
73
|
+
:attr:`bandwidth`.
|
|
73
74
|
exact_ppf : bool, optional
|
|
74
75
|
If True, :meth:`ppf` finds every value by root finding on
|
|
75
76
|
:meth:`cdf`, as funcsim did before version 0.2.7 (about 0.3 ms per
|
|
@@ -82,6 +83,14 @@ class Kde():
|
|
|
82
83
|
argument and a NumPy array of the same shape for an array-like argument
|
|
83
84
|
(a pandas Series or a list gives an array).
|
|
84
85
|
|
|
86
|
+
The two rules of thumb set the bandwidth to a factor times the sample
|
|
87
|
+
standard deviation ``s`` of the M observations, computed with
|
|
88
|
+
``ddof=1`` (dividing by M - 1, as :class:`scipy.stats.gaussian_kde`
|
|
89
|
+
does): Scott's rule gives ``M ** (-1 / 5) * s`` and Silverman's rule
|
|
90
|
+
``(3 * M / 4) ** (-1 / 5) * s``. (:class:`funcsim.MvKde` applies the
|
|
91
|
+
same factors to a ``ddof=0`` standard deviation, so on the same single
|
|
92
|
+
column its bandwidth is smaller by the factor ``sqrt((M - 1) / M)``.)
|
|
93
|
+
|
|
85
94
|
The inverse-CDF table evaluates the CDF on 4096 points spanning the data
|
|
86
95
|
range plus eight kernel standard deviations on each side, and
|
|
87
96
|
interpolates x against the normal score of the CDF with a
|
|
@@ -129,6 +138,18 @@ class Kde():
|
|
|
129
138
|
self._exact_ppf = bool(exact_ppf)
|
|
130
139
|
self._table = None # inverse-CDF table, built on first use
|
|
131
140
|
|
|
141
|
+
@property
|
|
142
|
+
def bandwidth(self) -> float:
|
|
143
|
+
"""
|
|
144
|
+
The bandwidth in use, the standard deviation of the Gaussian
|
|
145
|
+
kernel, in the units of the data.
|
|
146
|
+
|
|
147
|
+
For ``bw='scott'`` or ``bw='silverman'`` this is the rule's factor
|
|
148
|
+
(``gkde.factor``) times the sample standard deviation of the data
|
|
149
|
+
with ``ddof=1``; for a float ``bw`` it is that value.
|
|
150
|
+
"""
|
|
151
|
+
return math.sqrt(float(self.gkde.covariance[0, 0]))
|
|
152
|
+
|
|
132
153
|
@staticmethod
|
|
133
154
|
def _apply(func, x):
|
|
134
155
|
# evaluate a 1-D-array function on scalar or array-like input:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|