Правильный рейтинг на PHP
Несколько лет тому назад специально для одного проекта необходимо было рассчитывать рейтинг. Требования были несколько выше, чем простое суммирование голосов и деление на количество проголосовавших. Хотелось более объективной оценки при рейтинге и выдачи результатов (к тому же на данном проекте необходимо было учитывать еще и количество отзывов).
После относительно не долгих поисков на просторах сети интернет нашлось интересное решение, которое основывалось на доверительном интервале Вильсона. Источником для вдохновения послужил всем известный Хабрахабр и его статья «Как правильно сортировать контент на основе оценок пользователей«.
Доверительный интервал Вильсона можно использовать везде, где вы хотите с уверенностью знать, какова пропорция людей, совершающих определенный поступок.
А вот и сама формула, на которой основываются расчеты:
Словесное описание функции звучит как Рейтинг = Нижняя граница доверительного интервала Вильсона (Wilson) для параметра Бернулли.
Естественно, данная формула была адаптирована под произвольную шкалу голосов.
Вашему вниманию предлагаю функцию на PHP:
/** * Расчет рейтинга на основе шкалы голосов * * @param $sumVotes Сумма всех голосов * @param $totalVotes Кол-во голосов * @param array $votesRange Диапазон возможных значений голосов * @return float|int */ function wilsonScore($sumVotes, $totalVotes, $votesRange = [1, 2, 3, 4, 5]) { if ($sumVotes > 0 && $totalVotes > 0) { $z = 1.64485; $vMin = min($votesRange); $vWidth = floatval(max($votesRange) - $vMin); $phat = ($sumVotes - $totalVotes * $vMin) / $vWidth / floatval($totalVotes); $rating = ($phat + $z * $z / (2 * $totalVotes) - $z * sqrt(($phat * (1 - $phat) + $z * $z / (4 * $totalVotes)) / $totalVotes)) / (1 + $z * $z / $totalVotes); return round($rating * $vWidth + $vMin, 6); } return 0; }
На авторство не претендую, мне лишь понравилась сама функция на Python, которую я переделал под PHP, т.к. сайт работал именно на нем. Возможно кто-то использует более интересное решение. Буду рад всем вашим комментариям.
А вот таблица с тестовыми данными:
Сумма голосов | Какие были поставлены оценки | Кол-во голосов | Рейтинг |
5 | 5 | 1 | 2,079467 |
5 | 1+4 | 2 | 1,291229 |
5 | 2+2+1 | 3 | 1,093307 |
5 | 1+1+2+1 | 4 | 1,019701 |
5 | 1+1+1+1+1 | 5 | 1 |
15 | 5+5+5 | 3 | 3,103222 |
15 | 5+3+5+2 | 4 | 2,231445 |
15 | 5+2+5+3 | 4 | 2,231445 |
30 | 5+2+4+5+1+1+4+5+3 | 9 | 2,305087 |
30 | 4+4+5+4+3+5+5 | 7 | 3,042607 |
30 | 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 +1+1+1+1+1+1 | 30 | 1 |
30 | 1+1+1+1+1+1+1+1+1+2+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 +1+1+1 | 29 | 1,002707 |