wilson_score 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +16 -10
- data/lib/wilson_score.rb +23 -6
- data/lib/wilson_score/version.rb +1 -1
- data/test/wilson_score_test.rb +28 -8
- metadata +12 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d7bb501c73ead396229401fe42913d871b40415
|
4
|
+
data.tar.gz: 28ec167d67257eddf27488f0372fe26374e54f90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7df05093b79ad6080ec347db2f93aaca8f6cccb982dfabc7492e5c90dea6a8cd5c172731ff14c437224389eb82a2e61915a4a87cf3dd57b8911932c3f3ec8f7
|
7
|
+
data.tar.gz: b34ed9eec15dea13d48f523d91d5e4db1af62cdae38cf417f6dba92c971d4b673e6702decf21c56427e6206fa329b1f65daf7949b08f4b81fa15c09809980c3b
|
data/README.md
CHANGED
@@ -9,13 +9,25 @@ Inspired by [How Not To Sort By Average Rating](http://www.evanmiller.org/how-no
|
|
9
9
|
3 positive ratings out of 5 with 95% confidence
|
10
10
|
|
11
11
|
```ruby
|
12
|
-
WilsonScore.
|
12
|
+
WilsonScore.lower_bound(3, 5)
|
13
13
|
```
|
14
14
|
|
15
|
-
[Continuity correction](http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval_with_continuity_correction) can improve the score, especially for a small number of samples (n < 30).
|
15
|
+
[Continuity correction](http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson_score_interval_with_continuity_correction) can improve the score, especially for a small number of samples (n < 30). As of version 0.1.0, it is enabled by default. To disable continuity correction, use:
|
16
16
|
|
17
17
|
```ruby
|
18
|
-
WilsonScore.
|
18
|
+
WilsonScore.lower_bound(3, 5, correction: false)
|
19
|
+
```
|
20
|
+
|
21
|
+
The default confidence level is 95%. To change this, use:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
WilsonScore.lower_bound(3, 5, confidence: 0.99)
|
25
|
+
```
|
26
|
+
|
27
|
+
To get the full interval, use:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
WilsonScore.interval(3, 5)
|
19
31
|
```
|
20
32
|
|
21
33
|
## Star Ratings
|
@@ -28,16 +40,10 @@ A product has two ratings - one 4 star and one 5 star.
|
|
28
40
|
average_rating = 4.5
|
29
41
|
total_ratings = 2
|
30
42
|
rating_range = 1..5 # 1 to 5 stars
|
31
|
-
confidence = 0.95 # 95%
|
32
43
|
|
33
|
-
|
34
|
-
lower_bound = interval.first
|
44
|
+
WilsonScore.rating_lower_bound(average_rating, total_ratings, rating_range)
|
35
45
|
```
|
36
46
|
|
37
|
-
Use the lower bound of the interval to sort items.
|
38
|
-
|
39
|
-
Again, you can set the last parameter to `true` for continuity correction.
|
40
|
-
|
41
47
|
## Installation
|
42
48
|
|
43
49
|
Add this line to your application's Gemfile:
|
data/lib/wilson_score.rb
CHANGED
@@ -3,7 +3,12 @@ require "wilson_score/version"
|
|
3
3
|
module WilsonScore
|
4
4
|
|
5
5
|
# http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval
|
6
|
-
def self.interval(k, n,
|
6
|
+
def self.interval(k, n, *args)
|
7
|
+
args = args.dup
|
8
|
+
options = args[-1].is_a?(Hash) ? args.pop : {}
|
9
|
+
confidence = args[0] || options[:confidence] || 0.95
|
10
|
+
correction = !args[1].nil? ? args[1] : (options.has_key?(:correction) ? options[:correction] : true)
|
11
|
+
|
7
12
|
z = pnorm(1 - (1 - confidence) / 2.0)
|
8
13
|
phat = k / n.to_f
|
9
14
|
z2 = z**2
|
@@ -12,10 +17,9 @@ module WilsonScore
|
|
12
17
|
b = 2*n*phat + z2
|
13
18
|
c = z * Math.sqrt(z2 - 1.0/n + 4*n*phat*(1 - phat) + (4*phat - 2)) + 1
|
14
19
|
d = z * Math.sqrt(z2 - 1.0/n + 4*n*phat*(1 - phat) - (4*phat - 2)) + 1
|
15
|
-
|
16
|
-
|
17
|
-
upper
|
18
|
-
([0, lower].max)..([1, upper].min)
|
20
|
+
lower = phat == 0 ? 0 : [0, (b - c) / a].max
|
21
|
+
upper = phat == 1 ? 1 : [1, (b + d) / a].min
|
22
|
+
lower..upper
|
19
23
|
else
|
20
24
|
a = 1 + z2 / n
|
21
25
|
b = phat + z2 / (2 * n)
|
@@ -24,7 +28,16 @@ module WilsonScore
|
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
|
-
def self.
|
31
|
+
def self.lower_bound(k, n, options = {})
|
32
|
+
interval(k, n, options).first
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.rating_interval(avg, n, score_range, *args)
|
36
|
+
args = args.dup
|
37
|
+
options = args[-1].is_a?(Hash) ? args.pop : {}
|
38
|
+
confidence = args[0] || options[:confidence] || 0.95
|
39
|
+
correction = !args[1].nil? ? args[1] : (options.has_key?(:correction) ? options[:correction] : true)
|
40
|
+
|
28
41
|
min = score_range.first
|
29
42
|
max = score_range.last
|
30
43
|
range = max - min
|
@@ -32,6 +45,10 @@ module WilsonScore
|
|
32
45
|
(min + range * interval.first)..(min + range * interval.last)
|
33
46
|
end
|
34
47
|
|
48
|
+
def self.rating_lower_bound(avg, n, score_range, options = {})
|
49
|
+
rating_interval(avg, n, score_range, options).first
|
50
|
+
end
|
51
|
+
|
35
52
|
protected
|
36
53
|
|
37
54
|
# from the statistics2 gem
|
data/lib/wilson_score/version.rb
CHANGED
data/test/wilson_score_test.rb
CHANGED
@@ -3,51 +3,71 @@ require_relative "test_helper"
|
|
3
3
|
class TestWilsonScore < Minitest::Test
|
4
4
|
|
5
5
|
def test_wilson_score
|
6
|
-
interval = WilsonScore.interval(1, 2,
|
6
|
+
interval = WilsonScore.interval(1, 2, correction: false)
|
7
7
|
assert_in_delta 0.0945, interval.first
|
8
8
|
assert_in_delta 0.9055, interval.last
|
9
9
|
end
|
10
10
|
|
11
|
+
def test_lower_bound
|
12
|
+
assert_in_delta 0.0267, WilsonScore.lower_bound(1, 2)
|
13
|
+
end
|
14
|
+
|
11
15
|
def test_continuity_correction
|
12
|
-
interval = WilsonScore.interval(1, 2
|
16
|
+
interval = WilsonScore.interval(1, 2)
|
13
17
|
assert_in_delta 0.0267, interval.first
|
14
18
|
assert_in_delta 0.9733, interval.last
|
15
19
|
end
|
16
20
|
|
17
21
|
def test_continuity_correction_zero_one
|
18
|
-
interval = WilsonScore.interval(0, 1
|
22
|
+
interval = WilsonScore.interval(0, 1)
|
19
23
|
assert_in_delta 0, interval.first
|
20
24
|
assert_in_delta 0.9454, interval.last
|
21
25
|
end
|
22
26
|
|
27
|
+
def test_continuity_correction_zero_ten
|
28
|
+
interval = WilsonScore.interval(0, 10)
|
29
|
+
assert_in_delta 0, interval.first
|
30
|
+
assert_in_delta 0.3445, interval.last
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_continuity_correction_one_ten
|
34
|
+
interval = WilsonScore.interval(1, 10)
|
35
|
+
assert_in_delta 0.0052, interval.first
|
36
|
+
assert_in_delta 0.4588, interval.last
|
37
|
+
end
|
38
|
+
|
23
39
|
def test_continuity_correction_one_fifty
|
24
|
-
interval = WilsonScore.interval(1, 50
|
40
|
+
interval = WilsonScore.interval(1, 50)
|
25
41
|
assert_in_delta 0.0010, interval.first
|
26
42
|
assert_in_delta 0.1201, interval.last
|
27
43
|
end
|
28
44
|
|
29
45
|
def test_continuity_correction_one_one
|
30
|
-
interval = WilsonScore.interval(1, 1
|
46
|
+
interval = WilsonScore.interval(1, 1)
|
31
47
|
assert_in_delta 0.0546, interval.first
|
32
48
|
assert_in_delta 1, interval.last
|
33
49
|
end
|
34
50
|
|
35
51
|
def test_continuity_correction_one_three
|
36
|
-
interval = WilsonScore.interval(1, 3
|
52
|
+
interval = WilsonScore.interval(1, 3)
|
37
53
|
assert_in_delta 0.0176, interval.first
|
38
54
|
assert_in_delta 0.8747, interval.last
|
39
55
|
end
|
40
56
|
|
41
57
|
def test_rating
|
42
|
-
interval = WilsonScore.rating_interval(5, 1, 1..5,
|
58
|
+
interval = WilsonScore.rating_interval(5, 1, 1..5, correction: false)
|
43
59
|
assert_in_delta 1.8262, interval.first
|
44
60
|
assert_in_delta 5, interval.last
|
45
61
|
end
|
46
62
|
|
47
63
|
def test_rating_advanced
|
48
|
-
interval = WilsonScore.rating_interval(3.7, 10, 1..5,
|
64
|
+
interval = WilsonScore.rating_interval(3.7, 10, 1..5, correction: false)
|
49
65
|
assert_in_delta 2.4998, interval.first
|
50
66
|
assert_in_delta 4.5117, interval.last
|
51
67
|
end
|
52
68
|
|
69
|
+
def test_rating_lower_bound
|
70
|
+
assert_in_delta 1.8262, WilsonScore.rating_lower_bound(5, 1, 1..5, correction: false)
|
71
|
+
end
|
72
|
+
|
53
73
|
end
|
metadata
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wilson_score
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
description: Simple, dependency-free Wilson score
|
@@ -59,7 +59,7 @@ executables: []
|
|
59
59
|
extensions: []
|
60
60
|
extra_rdoc_files: []
|
61
61
|
files:
|
62
|
-
- .gitignore
|
62
|
+
- ".gitignore"
|
63
63
|
- Gemfile
|
64
64
|
- LICENSE.txt
|
65
65
|
- README.md
|
@@ -79,17 +79,17 @@ require_paths:
|
|
79
79
|
- lib
|
80
80
|
required_ruby_version: !ruby/object:Gem::Requirement
|
81
81
|
requirements:
|
82
|
-
- -
|
82
|
+
- - ">="
|
83
83
|
- !ruby/object:Gem::Version
|
84
84
|
version: '0'
|
85
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
requirements: []
|
91
91
|
rubyforge_project:
|
92
|
-
rubygems_version: 2.
|
92
|
+
rubygems_version: 2.2.0
|
93
93
|
signing_key:
|
94
94
|
specification_version: 4
|
95
95
|
summary: Simple, dependency-free Wilson score
|