A primary school measured every pupil's shoe size and reading score. Over the whole school, bigger feet go with better reading. Nobody believes that feet help with reading: older pupils have bigger feet and have had more years of reading practice. The school year is a confounder.
Each record is a tuple (year, shoe, score). Write adjusted_correlation(records) that returns a tuple (overall, within):
overallis the correlation coefficient ofshoeandscoreover all records;withinis the correlation coefficient after replacing every shoe size by its difference from the mean shoe size of its own year, and every score by its difference from the mean score of its own year, computed over all these differences together.
The correlation coefficient of paired lists is Sxy / sqrt(Sxx * Syy), with sums of products and squares of deviations from the means. When Sxx or Syy is 0 the coefficient is None.
The setup provides school_survey(n, seed, link), which returns n random records. Within a year, a pupil's reading score goes up by link points per shoe size (link=0 means feet and reading are unrelated within each year).
Examples
Input: records = [(1, 28, 40), (1, 30, 38), (1, 32, 42),
(2, 33, 55), (2, 35, 59), (2, 37, 57)]
Output: (0.8737708582753259, 0.5)
Explanation: over the whole school r is about 0.87. Within year 1 the differences
from the year means (30, 40) are (-2, 0), (0, -2), (2, 2); within year 2 (means 35, 57)
they are (-2, -2), (0, 2), (2, 0). Together they give Sxy = 8, Sxx = 16, Syy = 16, so r = 0.5.
Constraints
2 <= len(records) <= 5 * 10**4, at most 50 different years- shoe sizes and scores are integers or floats between
0and1000 - floats are compared with a tolerance of
1e-6
Goals
- Compute a correlation over all records and within groups
- Remove a confounder by comparing each record with its own group's means
- Explain a strong overall correlation that disappears inside every group