-
-
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
fiveStarRatingto 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!