I need to do auto-correlation of a set of numbers, which as I understand it is just the correlation of the set with itself.
I've tried it using numpy's correlate function, but I don't believe the result, as it almost always gives a vector where the first number is not the largest, as it ought to be.
So, this question is really two questions:
- What exactly is numpy.correlate doing?
- How can I use it (or something else) to do auto-correlation?
Your question 1 has been already extensively discussed in several excellent answers here.
I thought to share with you a few lines of code that allow you to compute the autocorrelation of a signal based only on the mathematical properties of the autocorrelation. That is, the autocorrelation may be computed in the following way:
subtract the mean from the signal and obtain an unbiased signal
compute the Fourier transform of the unbiased signal
compute the power spectral density of the signal, by taking the square norm of each value of the Fourier transform of the unbiased signal
compute the inverse Fourier transform of the power spectral density
normalize the inverse Fourier transform of the power spectral density by the sum of the squares of the unbiased signal, and take only half of the resulting vector
The code to do this is the following:
Plot the statistical autocorrelation given a pandas datatime Series of returns:
As I just ran into the same problem, I would like to share a few lines of code with you. In fact there are several rather similar posts about autocorrelation in stackoverflow by now. If you define the autocorrelation as
a(x, L) = sum(k=0,N-L-1)((xk-xbar)*(x(k+L)-xbar))/sum(k=0,N-1)((xk-xbar)**2)
[this is the definition given in IDL's a_correlate function and it agrees with what I see in answer 2 of question #12269834], then the following seems to give the correct results:As you see I have tested this with a sin curve and a uniform random distribution, and both results look like I would expect them. Note that I used
mode="same"
instead ofmode="full"
as the others did.To answer your first question,
numpy.correlate(a, v, mode)
is performing the convolution ofa
with the reverse ofv
and giving the results clipped by the specified mode. The definition of convolution, C(t)=∑ -∞ < i < ∞ aivt+i where -∞ < t < ∞, allows for results from -∞ to ∞, but you obviously can't store an infinitely long array. So it has to be clipped, and that is where the mode comes in. There are 3 different modes: full, same, & valid:t
where botha
andv
have some overlap.a
orv
).a
andv
completely overlap each other. The documentation fornumpy.convolve
gives more detail on the modes.For your second question, I think
numpy.correlate
is giving you the autocorrelation, it is just giving you a little more as well. The autocorrelation is used to find how similar a signal, or function, is to itself at a certain time difference. At a time difference of 0, the auto-correlation should be the highest because the signal is identical to itself, so you expected that the first element in the autocorrelation result array would be the greatest. However, the correlation is not starting at a time difference of 0. It starts at a negative time difference, closes to 0, and then goes positive. That is, you were expecting:autocorrelation(a) = ∑ -∞ < i < ∞ aivt+i where 0 <= t < ∞
But what you got was:
autocorrelation(a) = ∑ -∞ < i < ∞ aivt+i where -∞ < t < ∞
What you need to do is take the last half of your correlation result, and that should be the autocorrelation you are looking for. A simple python function to do that would be:
You will, of course, need error checking to make sure that
x
is actually a 1-d array. Also, this explanation probably isn't the most mathematically rigorous. I've been throwing around infinities because the definition of convolution uses them, but that doesn't necessarily apply for autocorrelation. So, the theoretical portion of this explanation may be slightly wonky, but hopefully the practical results are helpful. These pages on autocorrelation are pretty helpful, and can give you a much better theoretical background if you don't mind wading through the notation and heavy concepts.I use talib.CORREL for autocorrelation like this, I suspect you could do the same with other packages:
Using the
numpy.corrcoef
function instead ofnumpy.correlate
to calculate the statistical correlation for a lag of t: