accumulators 0.1.1 → 0.1.2

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