[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