Covariance studies how linearly two data sets, X and Y, vary with each other.
If Y goes up when X goes up, you expect a significant positive value.
If Y goes down when X goes up, you expect a significant negative value.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import display, HTML
from scipy.stats import pearsonr
%matplotlib inline
lX = np.arange(0, 10)
# Y1: X * 2
lY1 = lX * 2
# Y2: (X * 2) + 18
lY2 = (lX * 2) + 18
# Y3: Random normal
lY3 = np.random.randint(0, 18, 10)
plt.plot(lX, lY1, 'b')
plt.plot(lX, lY2, 'g')
plt.plot(lX, lY3, 'y')
plt.show()
Correlation
When Y increases as X increases, most of the sum terms sum up to a significant positive number.
lXRes = lX  lX.mean()
lY1Res = lY1  lY1.mean()
lFrame = pd.DataFrame({
'X': lXRes,
'Y1': lY1Res,
'XY1': lXRes * lY1Res,
}, columns=["x", "y1", "data"])
display(lFrame)
(lXRes * lY1Res).sum()

X 
Y1 
XY1 
0 
4.5 
9 
✔ 40.5 
1 
3.5 
7 
✔ 24.5 
2 
2.5 
5 
✔ 12.5 
3 
1.5 
3 
✔ 4.5 
4 
0.5 
1 
✔ 0.5 
5 
0.5 
1 
✔ 0.5 
6 
1.5 
3 
✔ 4.5 
7 
2.5 
5 
✔ 12.5 
8 
3.5 
7 
✔ 24.5 
9 
4.5 
9 
✔ 40.5 
This results in a positive covariance,
print("cov(X, Y1) = ", np.cov(lX, lY1)[0][1])
cov(X, Y1) = 18.3333333333
Anticorrelation
When Y decreases as X increases, most of the sum terms sum up to a significant negative number.
lXRes = lX  lX.mean()
lY2Res = lY2  lY2.mean()
lFrame = pd.DataFrame({
'x': lXRes,
'y2': lY2Res,
'data': lXRes * lY2Res,
}, columns=["x", "y2", "data"])
display(lFrame)
(lXRes * lY2Res).sum()

X 
Y2 
XY2 
0 
4.5 
9 
✔ 40.5 
1 
3.5 
7 
✔ 24.5 
2 
2.5 
5 
✔ 12.5 
3 
1.5 
3 
✔ 4.5 
4 
0.5 
1 
✔ 0.5 
5 
0.5 
1 
✔ 0.5 
6 
1.5 
3 
✔ 4.5 
7 
2.5 
5 
✔ 12.5 
8 
3.5 
7 
✔ 24.5 
9 
4.5 
9 
✔ 40.5 
This results in a negative covariance,
print("cov(X, Y2) = ", np.cov(lX, lY2)[0][1])
cov(X, Y2) = 18.3333333333
No correlation
When there is no correlation between X and Y, most of the sum terms cancel each other.
lY3Res = lY3  lY3.mean()
lFrame = pd.DataFrame({
'x': lXRes,
'y3': lY2Res,
'data': lXRes * lY3Res,
}, columns=["x", "y3", "data"])
display(lFrame)
(lXRes * lY3Res).sum()

X 
Y3 
XY3 
0 
4.5 
9 
✔ 21.6 
1 
3.5 
7 
✔ 9.8 
2 
2.5 
5 
✘13.0 
3 
1.5 
3 
✔ 5.7 
4 
0.5 
1 
✔ 1.4 
5 
0.5 
1 
✔ 2.6 
6 
1.5 
3 
✘ 2.7 
7 
2.5 
5 
✘ 7.0 
8 
3.5 
7 
✔ 4.2 
9 
4.5 
9 
✔ 32.4 
print("cov(X, Y3) = ", np.cov(lX, lY3)[0][1])
cov(X, Y3) = 6.11111111111
The problem with covariances as you see is, they are not comparable. Pearson’s
correlation coefficient computes a better measure of correlation by dividing
covariance by product of standard deviations of both data sets.