algorithm used to calculate 5 star ratings
-
01-06-2021 - |
Question
I need to calculate 5-star ratings like the one on Amazon website. I have done enough search to find what is the best algorithm, but I am not able to get a proper answer. For example, if these are the ratings
5 star - 252
4 star - 124
3 star - 40
2 star - 29
1 star - 33
totally 478 reviews
Amazon has calculated this to be "4.1 out of 5 stars". Can anyone tell me how this figure is arrived at? I am not able to get this just by doing average.
Solution
That's a weighted average, where you weigh each rating with the number of votes it got:
(5*252 + 4*124 + 3*40 + 2*29 + 1*33) / (252+124+40+29+33) = 4.11 and change
OTHER TIPS
If you are start calculation of overall rating from beginning then this formula will help you.
Formula
((Overall Rating * Total Rating) + new Rating) / (Total Rating + 1)
Example
suppose you have no ratings till now then formula is like, overall rating is "0" till now. total rating "0" and given rating is "4"
((0*0)+4)/1 = 4
If overall rating is "4.11" Total rating is "478" And new rating giving by one user is "2"
then formula is like
((4.11 * 478)+ 2)/479 // 479 is increment of new rating from 478
There is a really great write up on this topic at evanmiller.org. He goes through and discusses the pros and cons of a few approaches and suggests a mathematically reliable way of weighting and calculating votes.
a better way to do this,
rating = (sum_of_rating * 5)/sum_of_max_rating_of_user_count
example:
total users rated: 6
sum_of_max_rating_of_user_count: 6 x 5 = 30
sum_of_rating: 25
rating = (25 * 5) / 30
Done!
Yes, you can average them out:
(5 * 252 + 4 * 124 + 3 * 40 + 2 * 29 + 1 * 33) / 478 = 4.11
Super helpful reply by Blindy, here's the PHP code that's based on it. Some may find useful. The results will be 4.11 as per OP's example:
$ratings = array(
5 => 252,
4 => 124,
3 => 40,
2 => 29,
1 => 33
);
function calcAverageRating($ratings) {
$totalWeight = 0;
$totalReviews = 0;
foreach ($ratings as $weight => $numberofReviews) {
$WeightMultipliedByNumber = $weight * $numberofReviews;
$totalWeight += $WeightMultipliedByNumber;
$totalReviews += $numberofReviews;
}
//divide the total weight by total number of reviews
$averageRating = $totalWeight / $totalReviews;
return $averageRating;
}
How to build the above $ratings array
Example pseudo code, but which should work that explains how to build the $ratings array when info is stored in DB assuming you have a table called "ratings" and a column called "rating". In this case it's 1 join, you would need to do 4 joins to get all ratings, but this should get you started:
SELECT count(c1.rating) as one_star, count(c2.rating) as two_star
FROM ratings c1
LEFT OUTER JOIN
ratings c2
ON
c1.id = c2.id
WHERE
c1.rating = 1
AND
c2.rating = 2
another approach suggested in comments
SELECT SUM(rating = 1) AS one_s ,SUM(rating = 2) AS two_s ,SUM(rating = 3) as three_s FROM reviews where product_id = 9
This rating system is based on a weighted average or weighted mean. That is, they used the weight in terms of stars to compute a decimal value which rounds to 4.1. For example:
Sum of (weight * number of reviews at that weight) / total number of reviews
(5*252 + 4*124 + 3*40 + 2*29 + 1*33) / 478 = 4.1
Weighted average, sum the number of stars times its weight, and then divide it through by the total number of reviews.
You may want to check this algorithm out: Calculating Average Rating the Right Way using PHP and MySQL - there's no need of saving each "star" (aka rating grade) and its corresponding number of votes and then having to retrieve thousands of rows from the database every time you need to calculate their average. (unless you want to display exactly how many people rated the given item with 1, 2, 3, 4 & 5 stars)
in Javascript
function calcAverageRating(ratings) {
let totalWeight = 0;
let totalReviews = 0;
ratings.forEach((rating) => {
const weightMultipliedByNumber = rating.weight * rating.count;
totalWeight += weightMultipliedByNumber;
totalReviews += rating.count;
});
const averageRating = totalWeight / totalReviews;
return averageRating.toFixed(2);
}
const ratings = [
{
weight: 5,
count: 252
},
{
weight: 4,
count: 124
},
{
weight: 3,
count: 40
},
{
weight: 2,
count: 29
},
{
weight: 1,
count: 33
}
];
console.log(calcAverageRating(ratings));
According to your question your solution will be like this.
Sum of (Rate*TotalRatingOfThatRate)/ TotalNumberOfReviews
((5*252)+(4*124)+(3*40)+(2*29)+(1*33)) / (252+124+40+29+33)
output will be 4.1
(Total nunber of star / total number of persons who review * 5 ) * 5
= Answer
Fixed decimals in js to 1.
answer.toFixed(1);
Example the total reviews of 5 person is 20 star.
(20/5*5)*5 = 4.0
In addition, I am just trying to make practical and full code for all.
My Json Object Array
var yourRatingData =[{
review_id:1,
customer_id:5,
customer_name:"Faysal",
rating:5,
review_content:"I like this product it's cool and best in quality"
},
{
review_id:2,
customer_id:6,
customer_name:"Adams",
rating:4,
review_content:"It's quality product though price a bit high"
},
{
review_id:3,
customer_id:8,
customer_name:"Jane",
rating:3,
review_content:"I like but should improve quality"
},
{
review_id:4,
customer_id:9,
customer_name:"Julia",
rating:1,
review_content:"It's not good"
}];
Rating Calculation
let _5star = yourRatingData.filter(r=>r.rating==5).length;
let _4star = yourRatingData.filter(r=>r.rating==4).length;
let _3star = yourRatingData.filter(r=>r.rating==3).length;
let _2star = yourRatingData.filter(r=>r.rating==2).length;
let _1star = yourRatingData.filter(r=>r.rating==1).length;
//Sum of individual star.
let sumOfRating = parseInt( _5star + _4star + _3star + _2star + _1star );
//Total number of rating
let overallRating = parseInt( 5*_5star + 4*_4star + 3*_3star + 2*_2star +1*_1star );
//Average of all rating
let averageRating = parseFloat(overallRating/sumOfRating);
//Percentage of each star rating
let _5starPercentage = parseInt((_5star/totalRating)*100);
let _4starPercentage = parseInt((_4star/totalRating)*100);
let _3starPercentage = parseInt((_3star/totalRating)*100);
let _2starPercentage = parseInt((_2star/totalRating)*100);
let _1starPercentage = parseInt((_1star/totalRating)*100);
I think it's helpful.
with C#
double rating = (double)(5 * star5 + 4 * star4 + 3 * star3 + 2 * star2 + 1 * star1) / (star1 + star2 + star3 + star4 + star5);
rating = Math.Round(rating, 1);