array_stats 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,64 @@
1
+ = array_stats
2
+
3
+ * Docs[http://benkoski.com/array_stats/]
4
+ * Source[http://github.com/bkoski/array_stats]
5
+
6
+ == DESCRIPTION:
7
+
8
+ Simple statistics for ruby arrays -- mean, median, sum, and percentile. For more complex
9
+ applications, you should consider NArray[http://narray.rubyforge.org/].
10
+
11
+ == SYNOPSIS:
12
+
13
+ Adds convenient methods to grab stats from a Ruby array, including:
14
+ * mean
15
+ * median
16
+ * sum (named total_sum to avoid ActiveRecord conflicts)
17
+ * percentile
18
+
19
+ Percentile calculations are based on the NIST formula[http://www.itl.nist.gov/div898/handbook/prc/section2/prc252.htm] for percentiles.
20
+
21
+ == EXAMPLE:
22
+
23
+ require 'array_stats'
24
+
25
+ puts [1,3,5,7].mean
26
+ > 4
27
+
28
+ puts [1,2,3,4].total_sum
29
+ > 10
30
+
31
+ puts [1,2,3,4,5].median
32
+ > 3
33
+
34
+ puts [1,2,3,4,5].percentile(50)
35
+ > 3
36
+
37
+ == INSTALL:
38
+
39
+ * <tt>sudo gem install bkoski-array_stats --source http://gemcutter.org</tt>
40
+
41
+ == LICENSE:
42
+
43
+ (The MIT License)
44
+
45
+ Copyright (c) 2009 Ben Koski
46
+
47
+ Permission is hereby granted, free of charge, to any person obtaining
48
+ a copy of this software and associated documentation files (the
49
+ 'Software'), to deal in the Software without restriction, including
50
+ without limitation the rights to use, copy, modify, merge, publish,
51
+ distribute, sublicense, and/or sell copies of the Software, and to
52
+ permit persons to whom the Software is furnished to do so, subject to
53
+ the following conditions:
54
+
55
+ The above copyright notice and this permission notice shall be
56
+ included in all copies or substantial portions of the Software.
57
+
58
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
59
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
60
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
61
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
62
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
63
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
64
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "array_stats"
8
+ gem.summary = %Q{Easy mean, median, percentile, and sum statistics for Ruby Arrays}
9
+ gem.description = %Q{Easy mean, median, percentile, and sum statistics for Ruby Arrays}
10
+ gem.email = "gems@benkoski.com"
11
+ gem.homepage = "http://github.com/bkoski/array_stats"
12
+ gem.authors = ["Ben Koski"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "array_stats #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.6.0
@@ -0,0 +1,54 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{array_stats}
8
+ s.version = "0.6.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ben Koski"]
12
+ s.date = %q{2010-04-05}
13
+ s.description = %q{Easy mean, median, percentile, and sum statistics for Ruby Arrays}
14
+ s.email = %q{gems@benkoski.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ "README.rdoc",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "array_stats.gemspec",
23
+ "lib/array_stats.rb",
24
+ "lib/array_stats/array.rb",
25
+ "lib/array_stats/array_stats.rb",
26
+ "lib/array_stats/float.rb",
27
+ "test/test_array_stats.rb",
28
+ "test/test_float_extensions.rb",
29
+ "test/test_helper.rb"
30
+ ]
31
+ s.homepage = %q{http://github.com/bkoski/array_stats}
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.3.5}
35
+ s.summary = %q{Easy mean, median, percentile, and sum statistics for Ruby Arrays}
36
+ s.test_files = [
37
+ "test/test_array_stats.rb",
38
+ "test/test_float_extensions.rb",
39
+ "test/test_helper.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
48
+ else
49
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
50
+ end
51
+ else
52
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
53
+ end
54
+ end
@@ -0,0 +1,11 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module ArrayStats
5
+ VERSION = '0.5.0'
6
+ end
7
+
8
+ require "#{File.dirname(__FILE__)}/array_stats/float"
9
+ require "#{File.dirname(__FILE__)}/array_stats/array_stats"
10
+ require "#{File.dirname(__FILE__)}/array_stats/array"
11
+
@@ -0,0 +1,3 @@
1
+ class Array
2
+ include ArrayStats
3
+ end
@@ -0,0 +1,43 @@
1
+ module ArrayStats
2
+
3
+ # Returns the sum of all elements in the array; 0 if array is empty
4
+ def total_sum
5
+ self.inject(0) {|sum, sample| sum += sample}
6
+ end
7
+
8
+ # Returns the mean of all elements in array; nil if array is empty
9
+ def mean
10
+ if self.length == 0
11
+ nil
12
+ else
13
+ self.total_sum / self.length
14
+ end
15
+ end
16
+
17
+ # Returns the median for the array; nil if array is empty
18
+ def median
19
+ percentile(50)
20
+ end
21
+
22
+ # Returns the percentile value for percentile _p_; nil if array is empty.
23
+ #
24
+ # _p_ should be expressed as an integer; <tt>percentile(90)</tt> returns the 90th percentile of the array.
25
+ #
26
+ # Algorithm from NIST[http://www.itl.nist.gov/div898/handbook/prc/section2/prc252.htm]
27
+ def percentile p
28
+ sorted_array = self.sort
29
+ rank = (p.to_f / 100) * (self.length + 1)
30
+
31
+ if self.length == 0
32
+ return nil
33
+ elsif rank.fractional_part?
34
+ sample_0 = sorted_array[rank.truncate - 1]
35
+ sample_1 = sorted_array[rank.truncate]
36
+
37
+ return (rank.fractional_part * (sample_1 - sample_0)) + sample_0
38
+ else
39
+ return sorted_array[rank - 1]
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,13 @@
1
+ class Float
2
+
3
+ # Returns true if a float has a fractional part; i.e. <tt>f == f.to_i</tt>
4
+ def fractional_part?
5
+ fractional_part != 0.0
6
+ end
7
+
8
+ # Returns the fractional part of a float. For example, <tt>(6.67).fractional_part == 0.67</tt>
9
+ def fractional_part
10
+ (self - self.truncate).abs
11
+ end
12
+
13
+ end
@@ -0,0 +1,71 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestArrayStats < Test::Unit::TestCase
4
+
5
+ context "median" do
6
+ should "return the middle of the set if array length is odd" do
7
+ assert_equal 15, [1,2,15,22,38].median
8
+ end
9
+
10
+ should "return the average of the middle of the set if array length is even" do
11
+ assert_equal 10, [1,6,14,22].median
12
+ end
13
+
14
+ should "return nil if the array is empty" do
15
+ assert_nil [].median
16
+ end
17
+
18
+ should "sort an array before deriving the median" do
19
+ assert_equal 20, [1,20,50,60,10].median
20
+ end
21
+ end
22
+
23
+ context "percentile" do
24
+ should "choose the number at a particular rank if array divides cleanly" do
25
+ assert_equal 36, [12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48].percentile(65)
26
+ end
27
+
28
+ should "interpolate according to algorithm if array does not divide cleanly" do
29
+ assert_equal 5.5, [3,5,7,8,9,11,13,15].percentile(25)
30
+ assert_equal 95.1981, [95.1772,95.1567,95.1937,95.1959,95.1442,95.0610,95.1591,95.1195,95.1065,95.0925,95.1990,95.1682].percentile(90).round_to(0.0001)
31
+ end
32
+
33
+ should "return nil if the array is empty" do
34
+ assert_nil [].percentile(30)
35
+ end
36
+ end
37
+
38
+ context "total_sum" do
39
+ should "return the sum of all elements in the array" do
40
+ assert_equal 12, [2,4,6].total_sum
41
+ end
42
+
43
+ should "return an integer if all elements are ints" do
44
+ assert_kind_of Integer, [2,4,6].total_sum
45
+ end
46
+
47
+ should "return a float if at least some of the elements are floats" do
48
+ assert_kind_of Float, [2.5,3.5,6].total_sum
49
+ end
50
+
51
+ should "return 0 if the array is empty" do
52
+ assert_equal 0, [].total_sum
53
+ end
54
+ end
55
+
56
+ context "mean" do
57
+ should "return the mean for the array " do
58
+ assert_equal 7, [2,4,6,8,10,12].mean
59
+ assert_equal 25, [48,29,26,19,3].mean
60
+ end
61
+
62
+ should "return nil if the array is empty" do
63
+ assert_nil [].mean
64
+ end
65
+ end
66
+
67
+
68
+
69
+ end
70
+
71
+
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestFloatExtensions < Test::Unit::TestCase
4
+
5
+ context "fractional_part?" do
6
+ should "return true for a number with a fractional part" do
7
+ n = 1.249
8
+ assert n.fractional_part?
9
+ end
10
+
11
+ should "return true for a number without a fractional part" do
12
+ n = 1.0
13
+ assert !n.fractional_part?
14
+ end
15
+ end
16
+
17
+ context "fractional_part" do
18
+ should "return the decimal parts for a number" do
19
+ n = 12.2456
20
+ assert_in_delta 0.2456, n.fractional_part, 0.00000001
21
+ end
22
+
23
+ should "retrun the decimal parts, even if they are 0" do
24
+ n = 12.0
25
+ assert_equal 0.0, n.fractional_part
26
+ end
27
+
28
+ should "retrun the decimal as a positive number, even if the original float is negative" do
29
+ n = -12.2399
30
+ assert_in_delta 0.2399, n.fractional_part, 0.00000001
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../lib/array_stats'
4
+ require 'shoulda'
5
+ require 'facets'
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: array_stats
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Koski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-04-05 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Easy mean, median, percentile, and sum statistics for Ruby Arrays
26
+ email: gems@benkoski.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ files:
34
+ - README.rdoc
35
+ - Rakefile
36
+ - VERSION
37
+ - array_stats.gemspec
38
+ - lib/array_stats.rb
39
+ - lib/array_stats/array.rb
40
+ - lib/array_stats/array_stats.rb
41
+ - lib/array_stats/float.rb
42
+ - test/test_array_stats.rb
43
+ - test/test_float_extensions.rb
44
+ - test/test_helper.rb
45
+ has_rdoc: true
46
+ homepage: http://github.com/bkoski/array_stats
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --charset=UTF-8
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.5
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Easy mean, median, percentile, and sum statistics for Ruby Arrays
73
+ test_files:
74
+ - test/test_array_stats.rb
75
+ - test/test_float_extensions.rb
76
+ - test/test_helper.rb