Skip to content

13-01: Exercises — Correlation

Notes reference: 13-01: Correlation


Q1: Compute r by hand

Advertising spend (x, $000s) and sales (y, $000s) for 6 months:

x 2 4 5 7 8 10
y 30 38 45 52 58 67

Solution

x y xy
2 30 60 4 900
4 38 152 16 1444
5 45 225 25 2025
7 52 364 49 2704
8 58 464 64 3364
10 67 670 100 4489
Σ 36 Σ 290 Σ 1935 Σ 258 Σ 14926
n = 6

Numerator   = n(Σxy) − (Σx)(Σy) = 6(1935) − (36)(290)
            = 11610 − 10440 = 1170

Denominator = √[n(Σx²) − (Σx)²] · √[n(Σy²) − (Σy)²]
            = √[6(258) − 36²]   · √[6(14926) − 290²]
            = √[1548 − 1296]    · √[89556 − 84100]
            = √252              · √5456
            = 15.87451          × 73.86474
            = 1172.52

r = 1170 / 1172.52 = 0.99785

r² = 0.99571   →  99.6% of the variation in sales is explained by the
                  linear relationship with advertising spend.
=CORREL(A2:A7, B2:B7)      ' 0.997851
=RSQ(B2:B7, A2:A7)         ' 0.995707
x <- c(2,4,5,7,8,10); y <- c(30,38,45,52,58,67)
cor(x, y); cor(x, y)^2

Q2: Test the correlation

Test H₀: ρ = 0 for the Q1 data at α = 0.05.

Solution

                  ______
                 /n − 2                  ______
t  =  r  ·   √  ────────  =  0.99785 ·  √ 4/(1 − 0.99571)
                 1 − r²
                                             ______
                                 = 0.99785 ·  √ 4/0.004293
                                 = 0.99785 × √931.75
                                 = 0.99785 × 30.5246
                                 = 30.459

df = n − 2 = 4
critical t(0.025, 4) = ±2.7764
|30.459| > 2.7764                       →  REJECT H₀

p-value = 2 × P(T₄ > 30.459) = 0.0000069

CONCLUSION: the correlation is highly significant. Advertising spend and
sales are strongly linearly related in this population.

CAUTION: n = 6 is very small. A single unusual month would move r a great
deal. Collect more data before relying on this.
=CORREL(A2:A7,B2:B7)*SQRT(4/(1-CORREL(A2:A7,B2:B7)^2))   ' t -> 30.459
=T.DIST.2T(30.459, 4)                                     ' 0.0000069
=T.INV.2T(0.05, 4)                                        ' 2.77645
cor.test(x, y)
#  t = 30.459, df = 4, p-value = 6.93e-06
#  95 percent confidence interval: 0.9704 0.9998
res = stats.pearsonr(x, y)
res.statistic, res.pvalue
res.confidence_interval(0.95)

Q3: Interpret r values

For each, describe the relationship and give with its meaning.

r Description Meaning
+0.92 ? ? ?
−0.68 ? ? ?
+0.15 ? ? ?
0.00 ? ? ?
−0.99 ? ? ?

Solution

r Description Meaning
+0.92 Very strong positive linear 0.846 84.6% of variation in y explained
−0.68 Strong negative linear 0.462 46.2% explained
+0.15 Very weak positive linear 0.023 2.3% explained — essentially nothing
0.00 No linear relationship 0.000 0% explained (a curve could still exist!)
−0.99 Almost perfect negative linear 0.980 98.0% explained
THE MOST COMMON ERROR: reading r = 0.68 as "68% explained".
It is r² = 0.46 → 46%. Squaring matters, and it always makes the
relationship sound weaker than the raw r suggests.

r = 0.00 does NOT mean "no relationship". It means no LINEAR relationship.
Always plot the data before believing a correlation of zero.

Q4: Anscombe's quartet

Four data sets all have r = 0.816, the same means, and the same regression line. What does this prove?

Solution

SET 1  A genuine, well-behaved linear relationship with normal scatter.
       Correlation and regression are both appropriate.

SET 2  A perfect PARABOLA. The relationship is deterministic and strong,
       but it is CURVED — r understates it badly and a straight line is
       simply the wrong model. Fit a quadratic.

SET 3  A perfect straight line PLUS ONE OUTLIER. The outlier drags the
       line off the true relationship and pulls r down from 1.00 to 0.816.
       Investigate the outlier; consider a robust regression.

SET 4  All x values are identical EXCEPT ONE. That single point creates
       the entire correlation by itself. Remove it and r is undefined —
       there is no relationship at all, only one leverage point.

WHAT IT PROVES
    Summary statistics cannot substitute for a plot. Identical r, means,
    variances, and regression lines can come from four data sets with
    nothing in common. ALWAYS draw the scatterplot first.
data(anscombe)
sapply(1:4, function(i) cor(anscombe[[paste0("x",i)]], anscombe[[paste0("y",i)]]))
# 0.8164205 0.8162365 0.8162867 0.8165214

par(mfrow = c(2, 2))
for (i in 1:4) {
  x <- anscombe[[paste0("x", i)]]; y <- anscombe[[paste0("y", i)]]
  plot(x, y, pch = 19, col = "#5B2A86", main = paste("Set", i),
       xlim = c(4, 20), ylim = c(3, 13))
  abline(lm(y ~ x), col = "#0FA3A3", lwd = 2)
}
par(mfrow = c(1, 1))

Q5: The effect of one outlier

Data: x = 1,2,3,4,5,6,7,8,9,10, y = 2,4,5,4,5,7,8,9,10,12. Compute r. Then change the last y from 12 to 2 and recompute.

Solution

ORIGINAL
    Σx = 55,  Σy = 66,  Σxy = 446,  Σx² = 385,  Σy² = 524
    r = [10(446) − 55(66)] / (√[10(385) − 55²] · √[10(524) − 66²])
      = [4460 − 3630] / (√[3850 − 3025] · √[5240 − 4356])
      = 830 / (√825 · √884)
      = 830 / (28.7228 × 29.7321)
      = 830 / 853.87
      = 0.97205

WITH y₁₀ CHANGED FROM 12 TO 2
    Σy = 56,  Σxy = 346,  Σy² = 384
    r = [10(346) − 55(56)] / (√825 · √[10(384) − 56²])
      = [3460 − 3080] / (28.7228 × √[3840 − 3136])
      = 380 / (28.7228 × 26.5330)
      = 380 / 762.06
      = 0.49865

ONE CHANGED POINT out of ten drove r from 0.972 to 0.499 —
and r² from 94.5% to 24.9%.

WHY: r is built from products of deviations, and the changed point now
has a LARGE positive x-deviation paired with a LARGE negative
y-deviation, contributing strongly in the wrong direction. It is also a
high-leverage point because its x is at the edge of the range.

THE LESSON: r is NOT resistant. Always plot, and always check for
influential points before quoting a correlation.
x <- 1:10; y <- c(2,4,5,4,5,7,8,9,10,12)
cor(x, y)                        # 0.9721
y2 <- y; y2[10] <- 2
cor(x, y2)                       # 0.4987
cor(x, y2, method = "spearman")  # rank correlation — also drops, but less

Q6: Pearson vs. Spearman

Data: x = 1,2,3,4,5,6,7,8, y = 1,2,4,8,16,32,64,128 (exponential growth).

Compute both correlations and explain the difference.

Solution

PEARSON  r = 0.8505
    Measures LINEAR association. The relationship is exponential, so a
    straight line fits poorly and r falls short of 1.

SPEARMAN ρ = 1.0000
    Correlates the RANKS. Since y increases every time x increases, the
    ranks match perfectly and ρ = 1 — the relationship is perfectly
    MONOTONIC even though it is not linear.

WHEN TO USE WHICH
    PEARSON   both variables quantitative, relationship roughly linear,
              no severe outliers
    SPEARMAN  ordinal data, non-linear but monotonic relationships,
              outliers present, or ranks are all you have
    KENDALL   small samples with many tied ranks

FIXING THE PEARSON CASE
    Take logs:  cor(x, log(y)) = 1.0000 exactly, because log(y) is a
    perfectly linear function of x here. Transforming to linearity is
    often better than abandoning Pearson.
x <- 1:8; y <- 2^(0:7)
cor(x, y)                        # 0.8505  Pearson
cor(x, y, method = "spearman")   # 1.0000  Spearman
cor(x, log(y))                   # 1.0000  after transformation

plot(x, y, pch = 19, col = "#5B2A86")     # clearly curved
plot(x, log(y), pch = 19, col = "#0FA3A3") # perfectly straight
stats.pearsonr(x, y)
stats.spearmanr(x, y)
stats.pearsonr(x, np.log(y))

Q7: Correlation and causation

For each pair, name a plausible explanation other than "x causes y".

  1. Ice-cream sales and drowning deaths (r = 0.85)
  2. Number of firefighters at a fire and damage cost (r = 0.78)
  3. Shoe size and reading ability in children (r = 0.72)
  4. Countries' chocolate consumption and Nobel laureates per capita (r = 0.79)
  5. Hours of TV watched and body weight in adults (r = 0.35)

Solution

1. CONFOUNDER: temperature. Hot weather drives both ice-cream sales and
   swimming (hence drownings).

2. CONFOUNDER: fire size. Big fires attract more firefighters AND cause
   more damage. Sending fewer firefighters would not reduce damage.

3. CONFOUNDER: age. Older children have bigger feet AND read better.
   Within a single age group the correlation vanishes.

4. CONFOUNDER: national wealth. Rich countries buy more chocolate and
   fund more research. (This is a real, published, and deliberately
   tongue-in-cheek finding — with n = 23 countries.)

5. REVERSE CAUSATION and CONFOUNDING both plausible: heavier people may
   be less mobile and watch more TV; and income, occupation, and
   neighbourhood affect both.

THE FOUR EXPLANATIONS FOR ANY CORRELATION
    1. x causes y
    2. y causes x                (reverse causation)
    3. z causes both x and y     (confounding)
    4. coincidence               (especially when many pairs are screened)

ONLY a randomized experiment (08-01) can rule out 2, 3, and 4.

Q8: Build a correlation matrix

You have a data frame with age, income, education_years, hours_worked. Produce the correlation matrix with p-values and a scatterplot matrix.

Solution

' Data ▸ Data Analysis ▸ Correlation
'   Input Range = the whole numeric block, Grouped By: Columns, tick Labels
'   → a lower-triangular matrix of Pearson r values (NO p-values)
'
' For p-values, compute each one:
=CORREL(A2:A101, B2:B101)                                    ' r
=D2*SQRT((COUNT(A2:A101)-2)/(1-D2^2))                        ' t
=T.DIST.2T(ABS(E2), COUNT(A2:A101)-2)                        ' p
'
' Conditional formatting on the matrix makes the pattern visible:
'   Home ▸ Conditional Formatting ▸ Color Scales
round(cor(df), 3)                    # Pearson matrix
round(cor(df, method = "spearman"), 3)

library(psych)
corr.test(df)                        # r AND p-value matrices together

pairs(df, pch = 19, col = "#5B2A86") # scatterplot matrix

library(corrplot)
corrplot(cor(df), method = "color", addCoef.col = "black",
         tl.col = "black", col = colorRampPalette(c("#0FA3A3","white","#5B2A86"))(200))
df.corr().round(3)
df.corr(method="spearman").round(3)

# Matrix of p-values
cols = df.columns
pvals = pd.DataFrame(np.ones((len(cols), len(cols))), index=cols, columns=cols)
for a in cols:
    for b in cols:
        if a != b:
            pvals.loc[a, b] = stats.pearsonr(df[a], df[b]).pvalue
pvals.round(4)

pd.plotting.scatter_matrix(df, figsize=(8, 8), color="#5B2A86")
WHAT TO WATCH FOR IN A CORRELATION MATRIX
  • Very high correlations BETWEEN PREDICTORS (|r| > 0.8) warn of
    multicollinearity if you plan a regression (13-03).
  • With k variables you are looking at k(k−1)/2 correlations, so some
    will reach p < 0.05 by chance alone. With 4 variables that is 6
    tests; with 10 variables it is 45. Adjust (Bonferroni) or treat the
    matrix as exploratory.

⬅️ Previous: 12-03: Exercises — One-Way ANOVA ➡️ Next: 13-02: Exercises — Simple Linear Regression