skdh.utility.math.moving_mean#
- skdh.utility.math.moving_mean(a, w_len, skip, req_points=1.0, trim=True, axis=-1)#
Compute the moving mean.
- Parameters:
- aarray-like
Signal to compute moving mean for.
- w_lenint
Window length in number of samples.
- skipint
Window start location skip in number of samples.
- req_pointsfloat, optional
Minimum fraction of points required to compute the mean. Default is 1.0. If a float, is a proportion of the window length. If an int, is the number of points.
- trimbool, optional
Trim the ends of the result, where a value cannot be calculated. If False, these values will be set to NaN. Default is True.
- axisint, optional
Axis to compute the moving mean along. Default is -1.
- Returns:
- mmeannumpy.ndarray
Moving mean. Note that if the moving axis is not the last axis, then the result will not be c-contiguous.
Warning
Catastropic cancellation is a concern when skip is less than wlen due to the cumulative sum-type algorithm being used, when input values are very very large, or very very small. With typical IMU data values this should not be an issue, even for very long data series (multiple days worth of data)
Notes
On the moving axis if trim=True, the output length can be computed as follows:
\[\frac{n - w_{len}}{skip} + 1\]where n is the length of the moving axis. For cases where skip != 1 and trim=False, the length of the return on the moving axis can be calculated as:
\[\frac{n}{skip}\]Most efficient computations are for skip values that are either factors of wlen, or greater or equal to wlen.
Examples
Compute the with non-overlapping windows:
>>> import numpy as np >>> x = np.arange(10) >>> moving_mean(x, 3, 3) array([1., 4., 7.])
Compute with overlapping windows:
>>> moving_mean(x, 3, 1) array([1., 2., 3., 4., 5., 6., 7., 8.])
Compute without trimming the result
>>> moving_mean(x, 3, 1, trim=False) array([1., 2., 3., 4., 5., 6., 7., 8., nan, nan])
Compute on a nd-array to see output shape. On the moving axis, the output should be equal to \((n - w_{len}) / skip + 1\).
>>> n = 500 >>> window_length = 100 >>> window_skip = 50 >>> shape = (3, n, 5, 10) >>> y = np.random.random(shape) >>> res = moving_mean(y, window_length, window_skip, axis=1) >>> print(res.shape) (3, 9, 5, 10)
Check flags for different axis output
>>> z = np.random.random((10, 10, 10)) >>> moving_mean(z, 3, 3, axis=0).flags['C_CONTIGUOUS'] False
>>> moving_mean(z, 3, 3, axis=1).flags['C_CONTIGUOUS'] False
>>> moving_mean(z, 3, 3, axis=2).flags['C_CONTIGUOUS'] True