用于计算五星评级的算法

100

我需要计算类似亚马逊网站上5星评级的分数。我已经进行了足够的搜索,以找到最佳算法,但是我没有得到一个正确的答案。举个例子,如果这些是评分:

5 star - 252
4 star - 124
3 star - 40
2 star - 29
1 star - 33

共收到 478 条评论。

亚马逊计算出此产品的评分为“5 分制中的 4.1 分”。有人能告诉我这个数字是怎么算出来的吗?我只是简单地求平均数,但得不到这样的结果。


3
一个冗长的程序,用于显示平均星级计算。 - Sanju
13个回答

213

这是一种加权平均值,每个评分都会按其得票数进行加权:

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

17
这与“普通”平均数有何不同? - Jeff
7
与普通平均数相同。 - Daniel
2
是的,这与常规平均值相同。我们将(总星数)除以总用户数。由于分子中有乘法,因此看起来像加权。但如果我们重新表述它,本质上我们会将所有的5、4等加起来。由于5出现了252次,所以最终会变成5×252等等。 - theprogrammer
(51 + 41 + 31 + 21 + 1*1) / (1+1+1+1+1) = 3,但我们期望的是2.5,不是吗? - Natan Farkash
@Natan,如果评分范围是0-5而不是1-5,那么结果将是2.5。对于0-5的评分范围:(51 + 41 + 31 + 21 + 11 + 01)/(1+1+1+1+1+1)= 15 / 6 = 2.5。 - undefined
显示剩余3条评论

31

如果您从头开始计算总评分,则可以使用以下公式。

公式

((Overall Rating * Total Rating) + new Rating) / (Total Rating + 1)

示例

假设您目前没有任何评级,则公式如下, 总体评级现在为“0”。 总评级“0” 给定评级为“4”。

((0*0)+4)/1 = 4

如果整体评分为“4.11”,总评分为“478”,并且一个用户给出的新评分为“2”,则公式如下:
((4.11 * 478)+ 2)/479 // 479 is increment of new rating from 478

16

更好的做法,

rating = (sum_of_rating * 5)/sum_of_max_rating_of_user_count  

例子:

total users rated: 6  
sum_of_max_rating_of_user_count: 6 x 5 = 30  
sum_of_rating: 25

rating = (25 * 5) / 30

完成!


sum_of_max_rating_of_user_count 中的 5 代表什么?它是任何用户给出的最高评分吗? - andho
请解释一下....sum_of_max_rating_of_user_count: 6 x 5 = 30 ??? - thevikasnayak
6 是总共评价的用户数量。 5 是最大星级数(例如通常我们使用 5 星级评分)。 - Asad

11

是的,你可以计算它们的平均值:

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

9

Blindy提供了超级有用的回复,以下是基于他的回复编写的PHP代码。对一些人可能很有用。结果将与OP示例中的4.11相同:

$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;
}

如何构建以上的 $ratings 数组

以下是一个伪代码示例,它演示了如何构建 $ratings 数组,假设您有一个名为 "ratings" 的表和一个名为 "rating" 的列来存储信息。在这种情况下,只需要进行 1 次联接,但如果要获取所有评分,则需要进行 4 次联接,以下代码可供参考:

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

评论中提出的另一种方法

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

你已经创建了一个评分数组,我该如何使用MySQL创建这个数组。我的数据保存在数据库中。 - Ali Raza
1
@AliRaza 我已经更新了答案,你需要执行几个连接操作或使用5个单独的查询来获取数据。 - Robert Sinclair
1
我会说是你给了我这个想法,而我只是在上面工作。这个查询对我很有用: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 - Ali Raza

4
这个评分系统是基于加权平均加权算术平均数。也就是说,他们使用星级权重来计算一个四舍五入为4.1的小数值。例如:
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

3
根据您的问题,您的解决方案将如下所示。
Sum of (Rate*TotalRatingOfThatRate)/ TotalNumberOfReviews

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

输出结果将会是4.1


2

加权平均值,将星级数乘以其权重相加,然后除以总评论数。


1
这是一个使用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;
          });
        }
      }
    });
  }

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接