[wp-meta] [Making WordPress.org] #2686: Plugin Search: Search should also take into account the number of ratings
Making WordPress.org
noreply at wordpress.org
Tue May 12 02:10:59 UTC 2020
#2686: Plugin Search: Search should also take into account the number of ratings
------------------------------+-------------------------------------------
Reporter: bfintal | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Plugin Directory v3 - Future
Component: Plugin Directory | Resolution:
Keywords: needs-patch |
------------------------------+-------------------------------------------
Comment (by edo888):
Replying to [comment:14 gibrown]:
> If anyone has the time to create the php code for calculating a Wilson
score confidence interval for a Bernoulli parameter that would help make
this happen.
Here is a PHP implementation of https://github.com/instacart/wilson_score,
hope this helps
{{{#!php
<?php
class WilsonScore {
public function interval($k, $n, $options = array()) {
if($n == 0) {
echo "second parameter cannot be 0\n";
return false;
}
$confidence = isset($options['confidence']) ?
$options['confidence'] : 0.95;
$correction = isset($options['correction']) ?
$options['correction'] : true;
$z = $this->pnorm(1 - (1 - $confidence) / 2);
$phat = $k / $n;
$z2 = $z**2;
// continuity correction
if($correction) {
$a = 2 * ($n + $z2);
$b = 2 * $n * $phat + $z2;
$c = $z * sqrt($z2 - 1/$n + 4 * $n * $phat * (1 - $phat) + (4
* $phat - 2)) + 1;
$d = $z * sqrt($z2 - 1.0/$n + 4 * $n * $phat * (1 - $phat) -
(4 * $phat - 2)) + 1;
$lower = ($phat == 0 ? 0 : max(0, ($b - $c) / $a));
$upper = ($phat == 1 ? 1 : min(1, ($b + $d) / $a));
return array($lower, $upper);
} else {
$a = 1 + $z2 / $n;
$b = $phat + $z2 / (2 * $n);
$c = $z * sqrt(($phat * (1 - $phat) + $z2 / (4 * $n)) / $n);
return array(($b - $c) / $a, ($b + $c) / $a);
}
}
/**
* from the statistics2 gem
*
https://github.com/abscondment/statistics2/blob/master/lib/statistics2/base.rb
* inverse of normal distribution ([2])
* Pr( (-\infty, x] ) = qn -> x
*/
public function pnorm($qn) {
$b = array(1.570796288, 0.03706987906, -0.8364353589e-3,
-0.2250947176e-3, 0.6841218299e-5, 0.5824238515e-5,
-0.104527497e-5, 0.8360937017e-7, -0.3231081277e-8,
0.3657763036e-10, 0.6936233982e-12);
if($qn < 0.0 or 1.0 < $qn) {
echo "Error: qn <= 0 or qn >= 1 in pnorm()!\n";
return 0;
}
if($qn == 0.5)
return 0;
$w1 = $qn;
if($qn > 0.5)
$w1 = 1 - $w1;
$w3 = -log(4 * $w1 * (1 - $w1));
$w1 = $b[0];
for($i = 1; $i <= 10; $i++)
$w1 += $b[$i] * $w3 ** $i;
if($qn > 0.5)
return sqrt($w1 * $w3);
return -sqrt($w1 * $w3);
}
public function lower_bound($k, $n, $options = array()) {
return $this->interval($k, $n, $options)[0];
}
public function rating_interval($avg, $n, $score_range, $options =
array()) {
$confidence = isset($options['confidence']) ?
$options['confidence'] : 0.95;
$correction = isset($options['correction']) ?
$options['correction'] : true;
$min = $score_range[0];
$max = $score_range[1];
$range = $max - $min;
$interval = $this->interval($n * ($avg - $min) / $range, $n,
array('confidence' => $confidence, 'correction' => $correction));
return array(($min + $range * $interval[0]), ($min + $range *
$interval[1]));
}
public function rating_lower_bound($avg, $n, $score_range, $options =
array()) {
return $this->rating_interval($avg, $n, $score_range,
$options)[0];
}
}
}}}
Tests:
{{{#!php
<?php
<?php
include 'wilson_score.php';
$wilson = new WilsonScore;
function floats_eq($a, $b) {
return (abs($a - $b) < 0.0001);
}
function test_n($condition, &$n) {
if($condition === true)
echo "$n -> pass\n";
else
echo "$n -> fail\n";
$n++;
}
// test 1
$t = 1;
$interval = $wilson->interval(1, 2, array('correction' => false));
test_n(floats_eq(0.0945, $interval[0]) and floats_eq(0.9055,
$interval[1]), $t);
// test2
$lower_bound = $wilson->lower_bound(1, 2);
test_n(floats_eq(0.0267, $lower_bound), $t);
// test3
$interval = $wilson->interval(1, 2);
test_n(floats_eq(0.0267, $interval[0]) and floats_eq(0.9733,
$interval[1]), $t);
// test4
$interval = $wilson->interval(0, 1);
test_n(floats_eq(0, $interval[0]) and floats_eq(0.9454, $interval[1]),
$t);
// test5
$interval = $wilson->interval(0, 10);
test_n(floats_eq(0, $interval[0]) and floats_eq(0.3445, $interval[1]),
$t);
// test6
$interval = $wilson->interval(1, 10);
test_n(floats_eq(0.0052, $interval[0]) and floats_eq(0.4588,
$interval[1]), $t);
// test7
$interval = $wilson->interval(1, 50);
test_n(floats_eq(0.0010, $interval[0]) and floats_eq(0.1201,
$interval[1]), $t);
// test8
$interval = $wilson->interval(1, 1);
test_n(floats_eq(0.0546, $interval[0]) and floats_eq(1, $interval[1]),
$t);
// test9
$interval = $wilson->interval(1, 1);
test_n(floats_eq(0.0546, $interval[0]) and floats_eq(1, $interval[1]),
$t);
// test10
$interval = $wilson->interval(1, 3);
test_n(floats_eq(0.0176, $interval[0]) and floats_eq(0.8747,
$interval[1]), $t);
// test11
$interval = $wilson->rating_interval(5, 1, array(1, 5), array('correction'
=> false));
test_n(floats_eq(1.8262, $interval[0]) and floats_eq(5, $interval[1]),
$t);
// test12
$interval = $wilson->rating_interval(3.7, 10, array(1, 5),
array('correction' => false));
test_n(floats_eq(2.4998, $interval[0]) and floats_eq(4.5117,
$interval[1]), $t);
// test13
$rating_lower_bound = $wilson->rating_lower_bound(5, 1, array(1, 5),
array('correction' => false));
test_n(floats_eq(1.8262, $rating_lower_bound), $t);
// test14
test_n($wilson->interval(0, 0) == false, $t);
}}}
Test results
(https://github.com/instacart/wilson_score/blob/master/test/wilson_score_test.rb):
{{{
1 -> pass
2 -> pass
3 -> pass
4 -> pass
5 -> pass
6 -> pass
7 -> pass
8 -> pass
9 -> pass
10 -> pass
11 -> pass
12 -> pass
13 -> pass
second parameter cannot be 0
14 -> pass
}}}
--
Ticket URL: <https://meta.trac.wordpress.org/ticket/2686#comment:15>
Making WordPress.org <https://meta.trac.wordpress.org/>
Making WordPress.org
More information about the wp-meta
mailing list