Numerical differentiation: Time series
Cross-correlation and convolution of time series
The moving average is an example of a linear filter created by correlation and convolution of two time series. We explain what we mean by this. But first two definitions.
Definitions If and are time series then the cross-correlation (or in short, correlation) of these time series, denoted as , is defined by
If and are time series then the convolution of these time series, denoted , is defined by
Side note: there is no unique definition of correlation and convolution in the literature. We have used the convention as implemented in for example the numpy
module of the Python prgramming language. But these concepts always concern a product of a time series with another shifted time series. The visualisation below for the cross-correlation illustrates this.
We plot the time series and horizontally under an integer number line. As an example, we calculate .
Property The convolution operator is commutative, that is for time series and .
Property The convolution operator is associative, that is for time series , and .
A filter as cross-correlation Suppose we apply a weighted moving average with filter width and weights for to a time series . Then we get the new time series We can extend the weights to a time series by for . In other words, we extend on the left-hand and right-hand side with zeros. This time series is called the kernel of the filter and the nonzero elements are called filter coefficients. Then the above sum can be rewritten as or in short as But then we may write down that the time series is equal to the cross-correlation of the original time series and the kernel of the filter. So:
A filter as convolution Given the kernel of the linear filter, we define the adjoint of , denoted as , by placing the filter coefficients backwards; in other words for all . Then we can also write the weighted moving average as But then we may write down that the time series is equal to the convolution of the original time series and the adjoint of . So:
Example 1 Suppose that is a fixed number with . We take the time series and defined by and Then we can determine the cross-correlation and the convolution : The scatterplot of the filtered signal for also suggests that the value converges for large to :
Example 2 Calculating the results of filters can be done via computations with sparse matrices. The example below illustrates this using the weighted moving average with filter defined by In addition to the discrete time series , we choose for the second discrete time series the sequence defined by The time series resulting from cross-correlation of the time series and is then equal to This can be calculated on the basis of definitions, but also via matrix multiplication of sparse matrices (in which we take a coefficient equal to unless explicitly defined otherwise). We write only a finite part of the time series as a column vector and arrange the filter coefficients of as rows along the main diagonal in a matrix such that all non-zero filtered values can be computed; in this case we do this by
In Python, for example, calculating with (sparse) matrices is supported in the numpy
module and you can call the function correlate
for this calculation via:
>>> import numpy as np
>>> np.correlate([1, 3, 5, 7], [0.25, 0.5, 0.25], "full")
array([ 0.25, 1.25, 3. , 5. , 4.75, 1.75])
In other words, you calculate with finite signals via matrix vector multiplication. With the keywords "same" or valid" instead of "full" you get for a finite input signal an output signal with as many values as the input signal or with fewer values, because you do not calculate edge points by adding imaginary zeros to the initial signal at the edge.
>>> np.correlate([1, 3, 5, 7], [0.25, 0.5, 0.25], "same")
array([ 1.25, 3. , 5. , 4.75])
>>> np.correlate([1, 3, 5, 7], [0.25, 0.5, 0.25], "valid")
array([ 3. , 5.])
You can calculate the convolution of two time series in Python with the convolve
function. Because the chosen filter in this example is symmetrical, you get the same result:
>>> np.convolve([1, 3, 5, 7], [0.25, 0.5, 0.25], "full")
array([ 0.25, 1.25, 3. , 5. , 4.75, 1.75])