I sometimes curve exam scores using a linear scale of the general form $f(x) = mx + b$, where $x$ is the score to be curved.
To compute the parameters of the linear formula, I first calculate the average score on the exam, $\bar{x}$, and decide on an appropriate "perfect" score $x_p$ (which is often the maximum earned score, though it may also be different to mitigate "curve busters"). The job of the scaling formula is to map $\bar{x}$ to the desired average (typically 70%), and $x_p$ onto 100%. The following formula accomplishes this:
$$f(x) = 70 + \frac{100 - 70}{x_p - \bar{x}}(x-\bar{x})$$For example, if the average score on an exam is 60%, and the chosen perfect score is 95%, this gives us the equation:
$$f(x) = 70 + \frac{100 - 70}{95 - 60}(x-60) = 70 + \frac{30}{35}(x-60)$$The cell below shows the result of applying this specific curve to a variety of different values:
def f(x):
return 70 + (30/35)*(x-60)
[(x, f(x)) for x in range(40, 101, 5)]
Note that the formula will raise all scores, but will give an extra boost to lower scores. Scores above the "perfect score" will result in curved scores > 100%.
The following cell plots scores pre and post curve, based on this formula.
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
def plot_curve(xm, xp):
x = np.linspace(0, 100, 100)
y = (70+(30/(xp-xm))*(x-xm))
plt.plot(x, y, color='red', label='post-curve')
plt.plot(x, x, color='blue', label='pre-curve')
plt.legend(loc='upper left')
plt.grid()
plt.show()
plot_curve(60, 95)
The average on midterm 1 was 56%, and I determined 90% to be a reasonable "perfect" score (only two students scored higher than this). This gives us the following formula to compute the curves score:
$$f(x) = 70 + \frac{100 - 70}{90 - 56}(x-56) = 70 + \frac{30}{34}(x-56)$$def midterm1(x):
return 70 + (30/34)*(x-56)
[(x, f(x)) for x in range(40, 101, 5)]
Here's the corresponding plot:
plot_curve(56, 90)