pyhctsa.operations.entropy.sample_entropy_ranked

pyhctsa.operations.entropy.sample_entropy_ranked(y, m=2, r=0.1, pre_process_how=None, tau=1, theiler_win=0)

Sample entropy of the ranks of a time series: a SampEn that ignores the value distribution.

Computes sample_entropy() (SampEn; Richman & Moorman [1], PhysioNet code [2]) on the z-scored ranks of the series instead of on its values. The result depends only on the temporal order of the values: it is unchanged by any strictly increasing transformation of the data, and every iid series gives the same value up to sampling noise, whatever its marginal distribution, whereas the SampEn of the values depends on that distribution. Temporal regularity (autocorrelation, periodicity, deterministic dynamics) still lowers it.

Ranking the values is, up to scale, the probability integral transform with the empirical distribution function; Bajić et al. [4] study how this transform changes approximate and sample entropy. Other rank-based entropies rank the distances between templates rather than the values [5], or count ordinal patterns, as permutation entropy does [6].

Parameters:
y : array-like

Input time series.

m : int, optional

Maximum embedding dimension (template length), at least 1. Default is 2.

r : float, optional

Tolerance, in standard deviations of the ranks (default 0.1, the default tolerance of sample_entropy()). Two values match when their ranks differ by less than r * sqrt(N (N + 1) / 12), i.e. by less than a fraction r / sqrt(12) (0.058 for r = 0.2) of the sample, wherever they lie in the distribution.

pre_process_how : str, optional

'diff1': rank the first differences (increments) of the series, the rank analogue of the ‘Control Entropy’ of Bollt & Skufca [3] (sample_entropy with pre_process_how='diff1'); invariance then holds for the increments’ distribution. None (default): rank the series itself.

tau : int or str, optional

The template delay, as in sample_entropy(). A rule is applied to the ranks, so 'ac1e' here is the rank-based delay ('ac1e-rank' of the series), and the whole statistic stays invariant to strictly increasing transformations. Default 1.

theiler_win : int, float or [str, number], optional

The Theiler window, as in sample_entropy(), resolved on the ranks. Default 0.

Returns:

'sampen{k}' for k = 1..m: the SampEn of the ranks with templates of length k (NaN in the same cases as sample_entropy: when no templates of length k match, or when they do but none of length k + 1 do). All are NaN for a series with fewer than two distinct values, with fewer than two values (after differencing), or containing NaN or Inf. sample_entropy’s sampen0, quadSampEn{k} and meanchsampen are left out: the ranks of every length-N series are the same set of values, so sampen0 is a function of N and r only, quadSampEn{k} is sampen{k} plus a constant, and meanchsampen is (sampen{m} - sampen0) / m.

Return type:

dict

Notes

With R_t the rank of y_t among y_1, ..., y_N (1 to N), the series analysed is

\[u_t = \frac{R_t - (N + 1)/2}{\sqrt{N (N + 1) / 12}},\]

which has mean 0 and standard deviation 1 (ddof=1), and the output is sample_entropy(u, m, r)['sampen{k}']. For an iid continuous series, every sampen{k} estimates -log(2d - d^2) with d = r / sqrt(12) (2.19 for r = 0.2), whatever the distribution.

Uniform (plain) ranks are used rather than Gaussian scores of the ranks because they give every value nearly the same expected number of neighbours, whereas Gaussian scores leave few neighbours in the tails. Exactly equal values are ranked in a pseudo-random order (a fixed function of the data; see _ranks_random_ties), so that quantized or count-valued iid data behave like continuous iid data (average ranks would make tied values match each other).

References

Examples

>>> import numpy as np
>>> y = np.random.default_rng(0).standard_normal(1000)
>>> a = sample_entropy_ranked(y, m=2, r=0.2)
>>> b = sample_entropy_ranked(np.exp(3 * y), m=2, r=0.2)
>>> a == b
True