user1241438
user1241438

Reputation: 1543

algorithm used to calculate 5 star ratings

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.

Upvotes: 100

Views: 117352

Answers (13)

Labhansh Satpute
Labhansh Satpute

Reputation: 459

I used this way to calculate ratings and it is working perfectly

let one_star = 0;
let two_star = 0;
let three_star = 0;
let four_star = 0;
let five_star = 0;

Object.values(reviews).forEach(({ rating }) => {
  switch (rating) {
    case 1: one_star++; break;
    case 2: two_star++; break;
    case 3: three_star++; break;
    case 4: four_star++; break;
    case 5: five_star++; break;
  }
});

let sum = one_star + two_star + three_star + four_star + five_star;

let average = ((5 * five_star) + (4 * four_star) + (3 * three_star) + (2 * two_star) + (1 * one_star)) / (sum);

console.log(average);

Upvotes: 0

gsm
gsm

Reputation: 2426

This is an example method using flutter,

double starRating = 5.0;
  getRating() {
    // ! Check Already Accepted by others or Not -----------------------------------
    //
    int totalof5s = 0;
    int totalof4s = 0;
    int totalof3s = 0;
    int totalof2s = 0;
    int totalof1s = 0;
    //
    FirebaseFirestore.instance
        .collection('usersRating')
        .where("passengerUid", isEqualTo: "GNblJJJsjicaA2vkXJNJ6XCAiwa2")
        .snapshots()
        .forEach((querySnapshot) {
      if (querySnapshot.size > 0) {
        querySnapshot.docs.forEach((element) async {
          if (element["rating"] == 5) {
            totalof5s++;
          } else if (element["rating"] == 4) {
            totalof4s++;
          } else if (element["rating"] == 3) {
            totalof3s++;
          } else if (element["rating"] == 2) {
            totalof2s++;
          } else if (element["rating"] == 1) {
            totalof1s++;
          }
          //
          if (this.mounted) {
            setState(() {
              starRating = (5 * totalof5s +
                      4 * totalof4s +
                      3 * totalof3s +
                      2 * totalof2s +
                      1 * totalof1s) /
                  (totalof5s + totalof4s + totalof3s + totalof2s + totalof1s);
            });
          }
        });
        
      } else {
        // This is default one in any case these user doesn't have any rating document exists
        if (this.mounted) {
          setState(() {
            starRating = 5.0;
          });
        }
      }
    });
  }

Upvotes: 1

Pius T.K
Pius T.K

Reputation: 427

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

Upvotes: 3

Majedur
Majedur

Reputation: 3242

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.

Upvotes: 1

Flavio Marques
Flavio Marques

Reputation: 79

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));

Upvotes: 1

garbagecollector
garbagecollector

Reputation: 3880

Yes, you can average them out:

(5 * 252 + 4 * 124 + 3 * 40 + 2 * 29 + 1 * 33) / 478 = 4.11

Upvotes: 11

Jeremy Tangalan
Jeremy Tangalan

Reputation: 159

(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

Upvotes: 0

Robert Sinclair
Robert Sinclair

Reputation: 5426

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

Upvotes: 9

Asad
Asad

Reputation: 1439

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!

Upvotes: 17

SSKhan
SSKhan

Reputation: 410

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

Upvotes: 32

Nico
Nico

Reputation: 1191

Weighted average, sum the number of stars times its weight, and then divide it through by the total number of reviews.

Upvotes: 2

user830639
user830639

Reputation:

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

Upvotes: 4

Blindy
Blindy

Reputation: 67417

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

Upvotes: 213

Related Questions