wilson_score 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|