accumulators 0.1.1 → 0.1.2

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
data/accumulators.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{accumulators}
8
- s.version = "0.1.1"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Gavin Heavyside"]
@@ -33,8 +33,10 @@ Gem::Specification.new do |s|
33
33
  "lib/accumulators.rb",
34
34
  "lib/accumulators/count.rb",
35
35
  "lib/accumulators/mean.rb",
36
+ "lib/accumulators/meanvariance.rb",
36
37
  "spec/accumulators/count_spec.rb",
37
38
  "spec/accumulators/mean_spec.rb",
39
+ "spec/accumulators/meanvariance_spec.rb",
38
40
  "spec/spec_helper.rb"
39
41
  ]
40
42
  s.homepage = %q{http://github.com/hgavin/accumulators}
@@ -45,6 +47,7 @@ Gem::Specification.new do |s|
45
47
  s.test_files = [
46
48
  "spec/accumulators/count_spec.rb",
47
49
  "spec/accumulators/mean_spec.rb",
50
+ "spec/accumulators/meanvariance_spec.rb",
48
51
  "spec/spec_helper.rb"
49
52
  ]
50
53
 
data/lib/accumulators.rb CHANGED
@@ -1,3 +1,6 @@
1
1
  module Accumulators
2
+ autoload :Count, "accumulators/count"
3
+ autoload :Mean, "accumulators/mean"
4
+ autoload :MeanVariance, "accumulators/meanvariance"
2
5
  end
3
6
 
@@ -0,0 +1,44 @@
1
+
2
+ module Accumulators
3
+ class MeanVariance
4
+ attr_reader :count, :mean, :sumsq
5
+
6
+ def initialize
7
+ @count = 0
8
+ @mean = 0.0
9
+ @sumsq = 0.0
10
+ end
11
+
12
+ def add(rhs)
13
+ if rhs.is_a? Numeric
14
+ @count += 1
15
+ delta = rhs - @mean
16
+ @mean += delta/@count
17
+ @sumsq += delta * (rhs - @mean)
18
+ elsif rhs.is_a? MeanVariance
19
+ if rhs.count > 0
20
+ newCount = @count + rhs.count
21
+ delta = rhs.mean - @mean
22
+
23
+ newMean = @mean + delta*rhs.count/newCount
24
+ newSumsq = @sumsq + rhs.sumsq + delta*delta*@count*rhs.count/newCount
25
+
26
+ @count = newCount
27
+ @mean = newMean
28
+ @sumsq = newSumsq
29
+ end
30
+ else
31
+ raise ArgumentError
32
+ end
33
+ end
34
+
35
+ def variance
36
+ @count > 1 ? (@sumsq / (@count)) : 0.0
37
+ end
38
+
39
+ def stddev
40
+ Math.sqrt(variance)
41
+ end
42
+
43
+ end
44
+ end
@@ -1,8 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- require 'accumulators/count'
4
-
5
-
6
3
  describe "Accumulators" do
7
4
  describe "Count" do
8
5
  before :each do
@@ -1,9 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- require 'accumulators/mean'
4
-
5
- EPSILON = 0.00001
6
-
7
3
  describe "Accumulators" do
8
4
  describe "Mean" do
9
5
  before :each do
@@ -16,9 +12,8 @@ describe "Accumulators" do
16
12
  end
17
13
 
18
14
  it "returns count and mean of 0 before anything is added to it" do
19
- mean = Accumulators::Mean.new
20
- mean.count.should == 0
21
- mean.mean.should be_within(EPSILON).of(0.0)
15
+ @mean.count.should == 0
16
+ @mean.mean.should be_within(EPSILON).of(0.0)
22
17
  end
23
18
 
24
19
  end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe "Accumulators" do
5
+ describe "MeanVariance" do
6
+ before :each do
7
+ @meanvar = Accumulators::MeanVariance.new
8
+ end
9
+
10
+ context "Creation" do
11
+ it "can be created" do
12
+ lambda{ Accumulators::MeanVariance.new }.should_not raise_error
13
+ end
14
+
15
+ it "returns count,mean,var of 0,0.0,0.0 before anything is added" do
16
+ @meanvar.count.should == 0
17
+ @meanvar.mean.should be_within(EPSILON).of(0.0)
18
+ @meanvar.variance.should be_within(EPSILON).of(0.0)
19
+ end
20
+ end
21
+
22
+ context "adding numbers or distributions" do
23
+ it "allows integers to be added" do
24
+ lambda{ @meanvar.add 5 }.should_not raise_error
25
+ end
26
+
27
+ it "allows floats to be added" do
28
+ lambda{ @meanvar.add 5.5 }.should_not raise_error
29
+ end
30
+
31
+ it "allows other MeanVar distributions to be added" do
32
+ lambda{ @meanvar.add Accumulators::MeanVariance.new }.should_not raise_error
33
+ end
34
+
35
+ it "raises an ArgumentError if a string is added" do
36
+ lambda{ @meanvar.add "1.5" }.should raise_error(ArgumentError)
37
+ end
38
+
39
+ it "raises an ArgumentError if a Mean accumulator is added" do
40
+ lambda{ @meanvar.add Accumulators::Mean.new }.should raise_error(ArgumentError)
41
+ end
42
+ end
43
+
44
+ context "correctness of calcs when adding numbers" do
45
+ it "should calculate the mean and variance correctly for a set of numbers" do
46
+ vals = []
47
+ 1000.times do
48
+ vals << rand * 10000
49
+ @meanvar.add vals.last
50
+ end
51
+
52
+ @meanvar.count.should == vals.size
53
+ @meanvar.mean.should be_within(EPSILON).of(vals.reduce(:+)/vals.size)
54
+ @meanvar.variance.should be_within(EPSILON).of(vals.map{|v| (v - @meanvar.mean)**2}.reduce(:+) / vals.size)
55
+ end
56
+ end
57
+
58
+ context "correctness of calcs when adding MeanVariance accumulators" do
59
+ it "should combine two MeanVariances correctly" do
60
+ vals = []
61
+ mv2 = Accumulators::MeanVariance.new
62
+ 500.times do
63
+ vals << rand * 10000
64
+ @meanvar.add vals.last
65
+ vals << rand * 1000
66
+ mv2.add vals.last
67
+ end
68
+
69
+ @meanvar.add(mv2)
70
+
71
+ @meanvar.count.should == vals.size
72
+ @meanvar.mean.should be_within(EPSILON).of(vals.reduce(:+)/vals.size)
73
+ @meanvar.variance.should be_within(EPSILON).of(vals.map{|v| (v - @meanvar.mean)**2}.reduce(:+) / vals.size)
74
+ end
75
+ end
76
+
77
+ end
78
+ end
data/spec/spec_helper.rb CHANGED
@@ -7,6 +7,8 @@ require 'accumulators'
7
7
  # in ./support/ and its subdirectories.
8
8
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
9
 
10
+ EPSILON = 0.00001
11
+
10
12
  RSpec.configure do |config|
11
13
 
12
14
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Gavin Heavyside
@@ -101,8 +101,10 @@ files:
101
101
  - lib/accumulators.rb
102
102
  - lib/accumulators/count.rb
103
103
  - lib/accumulators/mean.rb
104
+ - lib/accumulators/meanvariance.rb
104
105
  - spec/accumulators/count_spec.rb
105
106
  - spec/accumulators/mean_spec.rb
107
+ - spec/accumulators/meanvariance_spec.rb
106
108
  - spec/spec_helper.rb
107
109
  has_rdoc: true
108
110
  homepage: http://github.com/hgavin/accumulators
@@ -118,7 +120,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
118
120
  requirements:
119
121
  - - ">="
120
122
  - !ruby/object:Gem::Version
121
- hash: 3832926264692213424
123
+ hash: 1520470741894311647
122
124
  segments:
123
125
  - 0
124
126
  version: "0"
@@ -140,4 +142,5 @@ summary: Statiscal accumulators for Ruby
140
142
  test_files:
141
143
  - spec/accumulators/count_spec.rb
142
144
  - spec/accumulators/mean_spec.rb
145
+ - spec/accumulators/meanvariance_spec.rb
143
146
  - spec/spec_helper.rb