Interpret bell curve, calculate 95th percentile value I have data showing the distribution of a given metric across a population.
The data is broken up into increments, with values for the 90th 97.5th and 99th percentiles.
How can I interpret this data to predict what the 95th percentile would be?




Percentile
1
2.5
10
20
30
40
50
60
70
80
90
97.5
99




Value
5.8
7.1
9.5
11
12.1
13.1
14
15.6
17.4
19.5
22.3
26.7
29.1



 A: My supposition is that the question expects you to assume that the distribution is a normal distribution. From there, you could assume that the mean of the distribution is estimated by the median (50th percentile), which in this case is 14.  And then the difference between the 50th percentile and 97.5th percentile is twice the estimate for the standard deviation (according to the 68–95–99.7 rule ( Wikipedia ).
What's curious, though, is that the difference between the 50th and 97.5th percentiles suggests an sd of 6.35 ((26.7 - 14) / 2).  Whereas the difference between the 50th and 2.5th percentiles suggests an sd of 3.45 ((14 - 7.1) / 2).
We could also estimate the sd from the the difference between the 2.5th and 97.5th percentiles (4.90, (26.7 - 7.1) / 4 ).
The upshot for me looking at the given data is that the percentiles <= 50 can be fit well with one normal distribution, and that the percentiles >= 50 can be fit well with a different normal distribution.
In the attached plots, the blue line uses mean = 14, sd = 6.35, and the light blue line uses mean = 14, sd = 3.45.  The gray line splits the difference and uses mean = 14, sd = 4.90.
Using the blue line would probably be the best way to estimate the 95th percentile.  Unless a better model could be found to estimate the whole distribution.
The R code I used follows.


Percentile = c(1, 2.5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 97.5, 
             99)/100
Value   = c(5.8, 7.1, 9.5, 11, 12.1, 13.1, 14, 15.6, 17.4, 19.5, 
            22.3, 26.7, 29.1)

P   = 0:10000 / 10000
M   = 14
SD  = (26.7 - 14)   / 2
SD2 = (14   -  7.1) / 2
SD3 = (26.7 -  7.1) / 4

plot(Percentile ~ Value, ylim=c(0,1.1), xlim=c(0, 35))

lines(qnorm(P, M, SD), P, col="blue", lwd=2)

lines(qnorm(P, M, SD2), P, col="cornflowerblue", lwd=2)

plot(Percentile ~ Value, ylim=c(0,1.1), xlim=c(0, 35))

lines(qnorm(P, M, SD3), P, col="darkgray", lwd=2)

Answer = qnorm(0.95, M, SD)

Answer

A: Two ways:
1. Linear interpolation (simple, but with a larger error): Interpolate between the 90th and 97.5th percentile. Your $x$ should be between 22.3 and 26.7, two-thirds towards the latter.
2. Curve fitting (computationally more complex, but more precise): You have $x$-values: 5.8, 7.1, ..., 29.1, and the corresponding $y$-values, which you should divide by 100 to get the probabilities: 0.01, 0.025, ..., 0.99. You adjust the $\mu$ and $\sigma$ parameters of the normal CDF, $\Phi(x; \mu, \sigma)$, to achieve the best fit between the given $y$-values and the ones given by $\Phi$. Finally, you calculate the inverse, $\Phi^{-1}(0.95; \mu, \sigma)$ to predict the 95th percentile.
Something like this:
import numpy as np
import scipy.optimize as opt
from scipy.stats import norm as gauss

# the data, as given in the question:
y = np.array([1, 2.5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 97.5, 99]) / 100
x = np.array([5.8, 7.1, 9.5, 11, 12.1, 13.1, 14, 15.6, 17.4, 19.5, 22.3, 26.7, 29.1])

# fit the Gaussian CDF to the data:
res = opt.minimize(
  lambda params: np.sum((gauss.cdf(x, loc=params[0], scale=params[1]) - y)**2),
  [10, 10]
)
# calculate the 95th percentile:
x_95 = gauss.ppf(.95, res.x[0], res.x[1])


#### the rest is just for visualisation:
import matplotlib.pyplot as plt

xx = np.linspace(5, 30, 100)
plt.plot(x, y, '.')
plt.plot(xx, gauss.cdf(xx, res.x[0], res.x[1]))
plt.plot([min(xx), x_95], [.95, .95], ':', c='k')
plt.plot([x_95, x_95], [0, .95], ':', c='k', label='$x_{95} = $' + f'{x_95:.2f}')
plt.legend()
plt.grid()
plt.title(f'$\mu$ = {res.x[0]:.2f}, $\sigma$ = {res.x[1]:.2f}')


