-
-
Save julienbourdeau/77eaca0fd1e4af3fde9fe018fdf13d7d to your computer and use it in GitHub Desktop.
<?php | |
/* | |
|-------------------------------------------------------------------------- | |
| 5 Star Rating | |
|-------------------------------------------------------------------------- | |
| | |
| Lower bound of Wilson score confidence interval for a Bernoulli parameter (0.9604) | |
| | |
| See: | |
| * http://www.evanmiller.org/how-not-to-sort-by-average-rating.html | |
| * https://gist.github.com/richardkundl/2950196 | |
| * https://onextrapixel.com/how-to-build-a-5-star-rating-system-with-wilson-interval-in-mysql/ | |
| | |
*/ | |
function score($positive, $negative) { | |
return ((($positive + 1.9208) / ($positive + $negative) - 1.96 * sqrt((($positive * $negative) / ($positive + $negative)) + 0.9604) / ($positive + $negative)) / (1 + 3.8416 / ($positive + $negative))); | |
} | |
function fiveStarRating($one, $two, $three, $four, $five) { | |
$positive = $two * 0.25 + $three * 0.5 + $four * 0.75 + $five; | |
$negative = $one + $two * 0.75 + $three * 0.5 + $four * 0.25; | |
return score($positive, $negative); | |
} | |
function fiveStarRatingAverage($avg, $total) | |
{ | |
$positive = ($avg * $total - $total) / 4; | |
$negative = $total - $positive; | |
return score($positive, $negative); | |
} | |
// Examples | |
echo fiveStarRating(10, 1, 2, 6, 90); // 0.80390178246001 | |
echo fiveStarRating(80, 1, 2, 6, 90); // 0.46188074417216 | |
echo fiveStarRating( 0, 1, 2, 6, 0 ); // 0.33136280289755 | |
echo fiveStarRating(10, 1, 2, 0, 2 ); // 0.079648861762752 | |
echo fiveStarRatingAverage(4.8000001907349, 10); // 0.65545605272928 | |
How do fiveStarRating
and fiveStarRatingAverage
compare in terms of the quality of the sorting? Do you have any data or examples?
Do you have a reference for the fiveStarRating
algo, or is it rather arbitrary?
Thanks, and thank you for sharing this snippet.
I don't know how different the result would be. I'd expect fiveStarRating
to be "better" and I'd use fiveStarRatingAverage
only if I lost the details and only stored avg and count but I don't really know.
My feeling is that this should only be one criteria and that it's hard to say that 0.46188074417216
is definitely better than 0.46188074417301`.
I'd expect
fiveStarRating
to be "better"
Actually I proved they're equal. Let's say that I want to implement fiveStarRatingAverage
with fiveStarRating
's parameters:
function fiveStarRatingAverage2($one, $two, $three, $four, $five)
{
// Doesn't compile, $avg, $total not defined
$positive = ($avg * $total - $total) / 4;
$negative = $total - $positive;
return score($positive, $negative);
}
Let's complete the implementation:
function fiveStarRatingAverage2($one, $two, $three, $four, $five)
{
$total = $one + $two + $three + $four + $five;
$avg = ($one * 1 + $two * 2 + $three * 3 + $four * 4 + $five * 5) / $total;
$positive = ($avg * $total - $total) / 4;
$negative = $total - $positive;
return score($positive, $negative);
}
Now let's inline $total
and $avg
into $positive
:
function fiveStarRatingAverage2($one, $two, $three, $four, $five)
{
$total = $one + $two + $three + $four + $five;
$positive = (($one * 1 + $two * 2 + $three * 3 + $four * 4 + $five * 5) - ($one + $two + $three + $four + $five)) / 4;
$negative = $total - $positive;
return score($positive, $negative);
}
And simplify:
function fiveStarRatingAverage2($one, $two, $three, $four, $five)
{
$total = $one + $two + $three + $four + $five;
$positive = $two * 0.25 + $three * 0.5 + $four * 0.75 + $five;
$negative = $total - $positive;
return score($positive, $negative);
}
Voila! We got the same calculation for $positive
. It's not difficult to figure out that $negative
is also equal for both functions.
Got it. Thanks!