Say I have a CDF of the form

$$F(x) = \sum_{i=1}^n \frac{ k_i }{ 1 + (x/\alpha_i)^{ - \beta_i } }$$

$$\sum_{i=1}^n k_i = 1$$

How do I find the quantile function, i.e. how do I invert F for n>1? I tried the simpler n=2 case by hand, but I'm getting nowhere. I also tried asking wolfram, but no luck.

If there is no closed-form solution, can you point to a (googleable) way to get a numerical approximation (say in python)?

  • 1
    $\begingroup$ This is the cdf for a mixture of distributions, not a sum. Are you sure it's the right expression? $\endgroup$ – whuber Feb 16 at 18:46
  • 1
    $\begingroup$ @whuber yes, it is a mixture. Yes I am sure, because I want to fit the pdf from one of the questions on this website, which is an aggregate of individual users' predictions (which are logistic distributions). $\endgroup$ – SCH Feb 16 at 20:48
  • 1
    $\begingroup$ Then numerical methods are needed. However, a great deal can be said about them. For instance, a favorite efficient root finder is Newton's method, but it may fail for quantiles near $1.$ The key is to find a good starting estimate; to bracket it; and to apply a transformation that will approximately linearize the problem. You can bracket the estimate with the range of quantiles of the individual components and you can linearize it (in the upper quantiles) by analyzing the logarithm of the CDF rather than the CDF itself. $\endgroup$ – whuber Feb 17 at 13:33

The case $n=1$ can be solved by algebra, I get $$ F^{-1}(p) = \frac{\alpha}{\exp\left( \frac{\log((1-p)/p}{\beta} \right)} $$ which can be used as a test for a numerical solution. For $n \ge 2$ only a numerical solution is practical, with R the function uniroot is helpful, there must be something similar in python. Some R code:

makeF <- 
function(k, alfa, beta) {
   n <- length(k)
   if(length(alfa)==1) alfa <- rep(alfa, n)
   if(length(beta)==1) beta <- rep(beta, n)
   k <- k/sum(k)
      Vectorize( function(x) sum(k/(1+(x/alfa)^(-beta))) )

to make the cdf. Then for the quantile function:

qF <- function(p, k, alfa, beta) {
F <- makeF(k,alfa,beta)
Vectorize( function(p) uniroot(function(x) F(x)-p, interval=c(0,1000),
                       extendInt="upX")$root )(p)

Then an example:

qF(c(0.2, 0.4, 0.6, 0.8), 1:3, 1:3, 2)
[1] 0.9999975 1.7621406 2.7914962 4.7475614
| cite | improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.