Search code examples
phprating-system

Wilson Confidence Interval for 5 stars rating system using goproblems.com


I have some problems by understanding the example on goproblem (http://www.goproblems.com/test/wilson/wilson.php?v1=0&v2=2&v3=0&v4=0&v5=0).

I have written my own code out from the example above (how i though it would work):

$stars = 4;
$n = 2;
$xbar = (($stars / $n)-1)/4;
$z = 0;
$Wilson = ((1 + 4 * (($xbar + pow($z,$n) / pow(2,$n) - $z) * sqrt($xbar * (1 - $xbar) / $n + pow($z,2) / 4 * pow($n,2))) / (1 + pow($z, 2) / $n)) - 0.374474917663);
echo $Wilson;

Now my problem here is i no not get the same lower bound score.. I figure there is something wrong with how i calculate, but i cannot figure out what..

Here is an example: The above link to goproblem opens up a result on lower bound score saying: 1.1067061310626. Now trying to mirror that (in the code above) i have the result: 0.9317113001849..

Something tells me i totally misunderstood something. Hope you guys can help me from here..


Solution

  • There is a class written by Mark Badolato that does exactly what you need, you can either use this library or learn from his implementation.

    class WilsonConfidenceIntervalCalculator {
        const CONFIDENCE = 1.959964;
    
        public function getScore($positiveVotes, $totalVotes) {
            return $totalVotes ? $this->lowerBound($positiveVotes, $totalVotes) : 0;
        }
    
        private function lowerBound($positiveVotes, $totalVotes) {
            $phat           = 1.0 * $positiveVotes / $totalVotes;
            $numerator      = $this->calculationNumerator($totalVotes, self::CONFIDENCE, $phat);
            $denominator    = $this->calculationDenominator($totalVotes, self::CONFIDENCE);
    
            return $numerator / $denominator;
        }
    
        private function calculationDenominator($total, $z) {
            return 1 + $z * $z / $total;
        }
    
        private function calculationNumerator($total, $z, $phat) {
            return $phat + $z * $z / (2 * $total) - $z * sqrt(($phat * (1 - $phat) + $z * $z / (4 * $total)) / $total);
        }
    }
    

    You can read more about this here and see how to run unit tests as well. https://gist.github.com/mbadolato/8253004