├── .gitignore ├── .simplecov ├── spec ├── safe │ ├── spec_helper.rb │ ├── stats_spec.rb │ ├── class_method_spec.rb │ └── extend_spec.rb ├── monkeypatch │ ├── spec_helper.rb │ ├── enumerable_spec.rb │ ├── single_value_spec.rb │ ├── array_spec.rb │ ├── set_spec.rb │ ├── hash_spec.rb │ ├── object_spec.rb │ └── empty_collection_spec.rb └── refinement │ ├── spec_helper.rb │ └── refinement_spec.rb ├── .travis.yml ├── lib ├── descriptive_statistics.rb └── descriptive_statistics │ ├── stats.rb │ ├── number.rb │ ├── enumerable_extension.rb │ ├── sum.rb │ ├── mean.rb │ ├── median.rb │ ├── range.rb │ ├── mode.rb │ ├── standard_deviation.rb │ ├── variance.rb │ ├── percentile_rank.rb │ ├── percentile.rb │ ├── refinement.rb │ ├── safe.rb │ ├── descriptive_statistics.rb │ ├── class_methods.rb │ └── support │ └── convert.rb ├── pkg └── descriptive_statistics-2.5.1.gem ├── Gemfile ├── descriptive_statistics.gemspec ├── Gemfile.lock ├── LICENSE ├── Rakefile ├── test ├── test.rb └── testdata.csv └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | -------------------------------------------------------------------------------- /.simplecov: -------------------------------------------------------------------------------- 1 | SimpleCov.start 2 | -------------------------------------------------------------------------------- /spec/safe/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | SimpleCov.command_name 'rspec:safe' -------------------------------------------------------------------------------- /spec/monkeypatch/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | SimpleCov.command_name 'rspec:monkeypatch' -------------------------------------------------------------------------------- /spec/refinement/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | SimpleCov.command_name 'rspec:refinement' -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.3.0 4 | before_install: 5 | - gem update --system 6 | - gem install bundler 7 | -------------------------------------------------------------------------------- /lib/descriptive_statistics.rb: -------------------------------------------------------------------------------- 1 | require "descriptive_statistics/safe" 2 | require "descriptive_statistics/enumerable_extension" 3 | -------------------------------------------------------------------------------- /pkg/descriptive_statistics-2.5.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thirtysixthspan/descriptive_statistics/HEAD/pkg/descriptive_statistics-2.5.1.gem -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "rake", :group => :development 4 | gem "rspec", :group => :test 5 | gem "simplecov", :require => false, :group => :test 6 | gem "minitest", :group => :test -------------------------------------------------------------------------------- /lib/descriptive_statistics/stats.rb: -------------------------------------------------------------------------------- 1 | require 'delegate' 2 | 3 | module DescriptiveStatistics 4 | 5 | class Stats < SimpleDelegator 6 | include DescriptiveStatistics 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/number.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | def number(collection = self, &block) 3 | values = Support::extract(collection, &block) 4 | 5 | values.to_a.size.to_f 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/enumerable_extension.rb: -------------------------------------------------------------------------------- 1 | module Enumerable 2 | include DescriptiveStatistics 3 | 4 | DescriptiveStatistics.instance_methods.each do |name| 5 | method = DescriptiveStatistics.instance_method(name) 6 | define_method(name, method) 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/sum.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | def sum(collection = self, &block) 3 | values = Support::convert(collection, &block) 4 | return DescriptiveStatistics.sum_empty_collection_default_value if values.empty? 5 | 6 | return values.reduce(:+) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/mean.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | def mean(collection = self, &block) 3 | values = Support::convert(collection, &block) 4 | return DescriptiveStatistics.mean_empty_collection_default_value if values.empty? 5 | 6 | values.sum / values.number 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/median.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | def median(collection = self, &block) 3 | values = Support::convert(collection, &block) 4 | return DescriptiveStatistics.median_empty_collection_default_value if values.empty? 5 | 6 | values.percentile(50) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/range.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | def range(collection = self, &block) 3 | values = Support::convert(collection, &block) 4 | return DescriptiveStatistics.range_empty_collection_default_value if values.empty? 5 | 6 | values.max - values.min 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/mode.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | def mode(collection = self, &block) 3 | values = Support::extract(collection, &block) 4 | return if values.to_a.empty? 5 | 6 | values 7 | .group_by { |e| e } 8 | .values 9 | .max_by(&:size) 10 | .first 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/standard_deviation.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | def standard_deviation(collection = self, &block) 3 | values = Support::convert(collection, &block) 4 | return DescriptiveStatistics.standard_deviation_empty_collection_default_value if values.empty? 5 | 6 | Math.sqrt(values.variance) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/variance.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | def variance(collection = self, &block) 3 | values = Support::convert(collection, &block) 4 | return DescriptiveStatistics.variance_empty_collection_default_value if values.empty? 5 | 6 | mean = values.mean 7 | values.map { |sample| (mean - sample) ** 2 }.reduce(:+) / values.number 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/percentile_rank.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | # percent of cases that are at or below a score 3 | def percentile_rank(p, collection = self, &block) 4 | values = Support::convert(collection, &block) 5 | return DescriptiveStatistics.percentile_rank_empty_collection_default_value if values.empty? 6 | 7 | return (((values.sort.rindex { |x| x <= p } || -1.0) + 1.0)) / values.number * 100.0 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/percentile.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | def percentile(p, collection = self, &block) 3 | values = Support::convert(collection, &block) 4 | 5 | return DescriptiveStatistics.percentile_empty_collection_default_value if values.empty? 6 | return values.first if values.size == 1 7 | 8 | values.sort! 9 | return values.last if p == 100 10 | rank = p / 100.0 * (values.size - 1) 11 | lower, upper = values[rank.floor,2] 12 | lower + (upper - lower) * (rank - rank.floor) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /spec/refinement/refinement_spec.rb: -------------------------------------------------------------------------------- 1 | require 'refinement/spec_helper' 2 | 3 | describe "DescriptiveStatistics" do 4 | require 'descriptive_statistics/refinement' 5 | 6 | it "is refinable" do 7 | 8 | class Test 9 | def self.unrefined 10 | [1, 2, 3].mean 11 | {a:1, b:2, c:3}.mean 12 | end 13 | 14 | using DescriptiveStatistics::Refinement.new(Array, Hash) 15 | 16 | def self.refined 17 | [1,2,3].mean 18 | {a:1, b:2, c:3}.mean 19 | end 20 | end 21 | 22 | expect{Test.unrefined}.to raise_error 23 | expect{Test.refined}.not_to raise_error 24 | 25 | end 26 | 27 | end -------------------------------------------------------------------------------- /descriptive_statistics.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = 'descriptive_statistics' 3 | s.version = '2.5.1' 4 | s.homepage = 'https://github.com/thirtysixthspan/descriptive_statistics' 5 | s.summary = 'Descriptive Statistics' 6 | s.description = 'Adds descriptive statistics methods to Enumerable module for use on collections or Numeric data' 7 | s.authors = ['Derrick Parkhurst', 'Gregory Brown', 'Daniel Farrell', 'Graham Malmgren', 'Guy Shechter', 'Charlie Egan'] 8 | s.email = 'derrick.parkhurst@gmail.com' 9 | s.files = Dir['lib/**/**/*'] 10 | s.license = "MIT" 11 | end 12 | 13 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/refinement.rb: -------------------------------------------------------------------------------- 1 | require "descriptive_statistics/safe" 2 | 3 | module DescriptiveStatistics 4 | 5 | module Refinement 6 | 7 | def self.new(*klasses) 8 | refinement_module = Module.new 9 | 10 | klasses.each do |klass| 11 | 12 | refinement_module.instance_eval do 13 | 14 | refine klass do 15 | 16 | DescriptiveStatistics.instance_methods.each do |name| 17 | method = DescriptiveStatistics.instance_method(name) 18 | define_method(name, method) 19 | end 20 | 21 | end 22 | 23 | end 24 | 25 | end 26 | 27 | return refinement_module 28 | 29 | end 30 | 31 | end 32 | 33 | end -------------------------------------------------------------------------------- /lib/descriptive_statistics/safe.rb: -------------------------------------------------------------------------------- 1 | require "descriptive_statistics/support/convert" 2 | require 'descriptive_statistics/number.rb' 3 | require 'descriptive_statistics/sum.rb' 4 | require 'descriptive_statistics/mean.rb' 5 | require 'descriptive_statistics/median.rb' 6 | require 'descriptive_statistics/mode.rb' 7 | require 'descriptive_statistics/variance.rb' 8 | require 'descriptive_statistics/standard_deviation.rb' 9 | require 'descriptive_statistics/percentile.rb' 10 | require 'descriptive_statistics/percentile_rank.rb' 11 | require 'descriptive_statistics/range.rb' 12 | require 'descriptive_statistics/descriptive_statistics.rb' 13 | require 'descriptive_statistics/stats.rb' 14 | require 'descriptive_statistics/class_methods.rb' 15 | 16 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/descriptive_statistics.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | def descriptive_statistics(&block) 3 | return { :number => self.number(&block), 4 | :sum => self.sum(&block), 5 | :variance => self.variance(&block), 6 | :standard_deviation => self.standard_deviation(&block), 7 | :min => self.min(&block), 8 | :max => self.max(&block), 9 | :mean => self.mean(&block), 10 | :mode => self.mode(&block), 11 | :median => self.median(&block), 12 | :range => self.range(&block), 13 | :q1 => self.percentile(25, &block), 14 | :q2 => self.percentile(50, &block), 15 | :q3 => self.percentile(75, &block) } 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | diff-lcs (1.2.5) 5 | docile (1.1.5) 6 | minitest (5.8.4) 7 | multi_json (1.10.1) 8 | rake (10.4.2) 9 | rspec (3.1.0) 10 | rspec-core (~> 3.1.0) 11 | rspec-expectations (~> 3.1.0) 12 | rspec-mocks (~> 3.1.0) 13 | rspec-core (3.1.7) 14 | rspec-support (~> 3.1.0) 15 | rspec-expectations (3.1.2) 16 | diff-lcs (>= 1.2.0, < 2.0) 17 | rspec-support (~> 3.1.0) 18 | rspec-mocks (3.1.3) 19 | rspec-support (~> 3.1.0) 20 | rspec-support (3.1.2) 21 | simplecov (0.9.1) 22 | docile (~> 1.1.0) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.8.0) 25 | simplecov-html (0.8.0) 26 | 27 | PLATFORMS 28 | ruby 29 | 30 | DEPENDENCIES 31 | minitest 32 | rake 33 | rspec 34 | simplecov 35 | -------------------------------------------------------------------------------- /spec/monkeypatch/enumerable_spec.rb: -------------------------------------------------------------------------------- 1 | require 'monkeypatch/spec_helper' 2 | 3 | describe "DescriptiveStatistics" do 4 | require 'descriptive_statistics' 5 | 6 | class Foo 7 | include Enumerable 8 | attr_accessor :bar, :baz, :bat 9 | 10 | def each 11 | Enumerator.new do |y| 12 | y << @bar 13 | y << @baz 14 | y << @bat 15 | end 16 | end 17 | end 18 | 19 | subject { Foo.new } 20 | 21 | context "with a class that includes Enumerable" do 22 | 23 | it "responds to all statistics methods" do 24 | DescriptiveStatistics.instance_methods.each do |method| 25 | expect(subject).respond_to? method 26 | end 27 | end 28 | 29 | it "calculates statistics" do 30 | subject.bar = 1 31 | subject.baz = 2 32 | subject.bat = 3 33 | expect(subject.mean).to eql(2.0) 34 | end 35 | 36 | end 37 | 38 | end 39 | -------------------------------------------------------------------------------- /lib/descriptive_statistics/class_methods.rb: -------------------------------------------------------------------------------- 1 | module DescriptiveStatistics 2 | 3 | class << self 4 | 5 | def empty_collection_default_value 6 | @empty_collection_default_value 7 | end 8 | 9 | def empty_collection_default_value=(value) 10 | @empty_collection_default_value = value 11 | DescriptiveStatistics.instance_methods.each { |m| default_values[m] = value } 12 | end 13 | 14 | DescriptiveStatistics.instance_methods.each do |m| 15 | define_method("#{m}_empty_collection_default_value") do 16 | default_values[m] 17 | end 18 | define_method("#{m}_empty_collection_default_value=") do |value| 19 | default_values[m] = value 20 | end 21 | end 22 | 23 | private 24 | 25 | def default_values 26 | @default_values ||= {} 27 | end 28 | 29 | end 30 | 31 | DescriptiveStatistics.instance_methods.each do |method| 32 | module_function method 33 | public method 34 | end 35 | 36 | end -------------------------------------------------------------------------------- /lib/descriptive_statistics/support/convert.rb: -------------------------------------------------------------------------------- 1 | require 'set' 2 | 3 | module DescriptiveStatistics 4 | 5 | module Support 6 | 7 | def self.convert(from_enumerable, &block) 8 | extend to_float to_value(to_array(from_enumerable), &block) 9 | end 10 | 11 | def self.extract(from_enumerable, &block) 12 | extend to_value(to_array(from_enumerable), &block) 13 | end 14 | 15 | private 16 | 17 | def self.extend(enumerable) 18 | enumerable.extend(DescriptiveStatistics) 19 | end 20 | 21 | def self.to_float(enumerable) 22 | enumerable.map(&:to_f) 23 | end 24 | 25 | def self.to_value(enumerable, &block) 26 | return enumerable unless block_given? 27 | enumerable.map { |object| yield object } 28 | end 29 | 30 | def self.to_array(enumerable) 31 | case enumerable 32 | when Hash 33 | enumerable.values.each 34 | when Set 35 | enumerable.to_a.each 36 | else 37 | enumerable.each 38 | end 39 | end 40 | 41 | end 42 | 43 | end 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2014 Derrick Parkhurst (derrick.parkhurst@gmail.com) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | require 'bundler/gem_tasks' 3 | require 'rake/testtask' 4 | 5 | Rake::TestTask.new do |t| 6 | t.test_files = FileList['test/*.rb'] 7 | t.verbose = true 8 | end 9 | 10 | begin 11 | require 'rspec/core/rake_task' 12 | 13 | RSpec::Core::RakeTask.new(:refinement) do |task| 14 | task.rspec_opts = "--order rand" 15 | task.pattern = "spec/refinement/*_spec.rb" 16 | end 17 | 18 | RSpec::Core::RakeTask.new(:monkeypatch) do |task| 19 | task.rspec_opts = "--order rand" 20 | task.pattern = "spec/monkeypatch/*_spec.rb" 21 | end 22 | 23 | RSpec::Core::RakeTask.new(:safe) do |task| 24 | task.rspec_opts = "--order rand" 25 | task.pattern = "spec/safe/*_spec.rb" 26 | end 27 | 28 | rescue LoadError 29 | warn "rspec unavailable" 30 | end 31 | 32 | task :default do 33 | Rake::Task["test"].invoke 34 | Rake::Task["monkeypatch"].invoke 35 | Rake::Task["safe"].invoke 36 | Rake::Task["refinement"].invoke if ruby_major >= 2 && ruby_minor >= 1 37 | end 38 | 39 | def ruby_major 40 | RUBY_VERSION.split(/\./)[0].to_i 41 | end 42 | 43 | def ruby_minor 44 | RUBY_VERSION.split(/\./)[1].to_i 45 | end 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /spec/monkeypatch/single_value_spec.rb: -------------------------------------------------------------------------------- 1 | require 'monkeypatch/spec_helper' 2 | 3 | describe "DescriptiveStatistics" do 4 | require 'descriptive_statistics' 5 | 6 | subject { [2] } 7 | 8 | context "with a single value array" do 9 | 10 | it "calculates the number" do 11 | expect(subject.number).to eql(1.0) 12 | end 13 | 14 | it "calculates the sum" do 15 | expect(subject.sum).to eql(2.0) 16 | end 17 | 18 | it "calculates the mean" do 19 | expect(subject.mean).to eql(2.0) 20 | end 21 | 22 | it "calculates the median" do 23 | expect(subject.median).to eql(2.0) 24 | end 25 | 26 | it "calculates the variance" do 27 | expect(subject.variance).to eql(0.0) 28 | end 29 | 30 | it "calculates the standard_deviation" do 31 | expect(subject.standard_deviation).to eql(0.0) 32 | end 33 | 34 | it "calculates the percentile" do 35 | expect(subject.percentile(30)).to eql(2.0) 36 | expect(subject.percentile(50)).to eql(2.0) 37 | expect(subject.percentile(70)).to eql(2.0) 38 | end 39 | 40 | it "calculates the same value for the 50th percentile and median" do 41 | expect(subject.percentile(50)).to eql(subject.median) 42 | end 43 | 44 | it "calculates the mode" do 45 | expect(subject.mode).to eql(2) 46 | end 47 | 48 | it "calculates the range" do 49 | expect(subject.range).to eql(0.0) 50 | end 51 | 52 | it "calculates the percentile rank" do 53 | expect(subject.percentile_rank(2)).to eql(100.0) 54 | end 55 | 56 | end 57 | 58 | end -------------------------------------------------------------------------------- /spec/safe/stats_spec.rb: -------------------------------------------------------------------------------- 1 | require 'safe/spec_helper' 2 | 3 | describe "DescriptiveStatistics" do 4 | require 'descriptive_statistics/safe' 5 | 6 | context "calculated from a Stats object" do 7 | 8 | subject { DescriptiveStatistics::Stats.new([2,6,9,3,5,1,8,3,6,9,2]) } 9 | 10 | it "calculates the number" do 11 | expect(subject.number).to eql(11.0) 12 | end 13 | 14 | it "calculates the sum" do 15 | expect(subject.sum).to eql(54.0) 16 | end 17 | 18 | it "calculates the mean" do 19 | expect(subject.mean).to eql(4.909090909090909) 20 | end 21 | 22 | it "calculates the median" do 23 | expect(subject.median).to eql(5.0) 24 | end 25 | 26 | it "calculates the variance" do 27 | expect(subject.variance).to eql(7.7190082644628095) 28 | end 29 | 30 | it "calculates the standard_deviation" do 31 | expect(subject.standard_deviation).to eql(2.778310325442932) 32 | end 33 | 34 | it "calculates the percentile" do 35 | expect(subject.percentile(30)).to eql(3.0) 36 | expect(subject.percentile(50)).to eql(5.0) 37 | expect(subject.percentile(70)).to eql(6.0) 38 | end 39 | 40 | it "calculates the same value for the 50th percentile and median" do 41 | expect(subject.percentile(50)).to eql(subject.median) 42 | end 43 | 44 | it "calculates the mode" do 45 | expect(subject.mode).to eql(2) 46 | end 47 | 48 | it "calculates the range" do 49 | expect(subject.range).to eql(8.0) 50 | end 51 | 52 | it "calculates the percentile rank" do 53 | expect(subject.percentile_rank(8)).to eql(81.81818181818183) 54 | end 55 | 56 | end 57 | 58 | end -------------------------------------------------------------------------------- /spec/safe/class_method_spec.rb: -------------------------------------------------------------------------------- 1 | require 'safe/spec_helper' 2 | 3 | describe "DescriptiveStatistics" do 4 | require 'descriptive_statistics/safe' 5 | 6 | context "calculated using class methods" do 7 | 8 | let(:data) { [2,6,9,3,5,1,8,3,6,9,2] } 9 | subject { DescriptiveStatistics } 10 | 11 | it "calculates the number" do 12 | expect(subject.number(data)).to eql(11.0) 13 | end 14 | 15 | it "calculates the sum" do 16 | expect(subject.sum(data)).to eql(54.0) 17 | end 18 | 19 | it "calculates the mean" do 20 | expect(subject.mean(data)).to eql(4.909090909090909) 21 | end 22 | 23 | it "calculates the median" do 24 | expect(subject.median(data)).to eql(5.0) 25 | end 26 | 27 | it "calculates the variance" do 28 | expect(subject.variance(data)).to eql(7.7190082644628095) 29 | end 30 | 31 | it "calculates the standard_deviation" do 32 | expect(subject.standard_deviation(data)).to eql(2.778310325442932) 33 | end 34 | 35 | it "calculates the percentile" do 36 | expect(subject.percentile(30, data)).to eql(3.0) 37 | expect(subject.percentile(50, data)).to eql(5.0) 38 | expect(subject.percentile(70, data)).to eql(6.0) 39 | end 40 | 41 | it "calculates the same value for the 50th percentile and median" do 42 | expect(subject.percentile(50, data)).to eql(subject.median(data)) 43 | end 44 | 45 | it "calculates the mode" do 46 | expect(subject.mode(data)).to eql(2) 47 | end 48 | 49 | it "calculates the range" do 50 | expect(subject.range(data)).to eql(8.0) 51 | end 52 | 53 | it "calculates the percentile rank" do 54 | expect(subject.percentile_rank(8, data)).to eql(81.81818181818183) 55 | end 56 | 57 | end 58 | 59 | end -------------------------------------------------------------------------------- /spec/monkeypatch/array_spec.rb: -------------------------------------------------------------------------------- 1 | require 'monkeypatch/spec_helper' 2 | 3 | describe "DescriptiveStatistics" do 4 | require 'descriptive_statistics' 5 | 6 | subject { [2,6,9,3,5,1,8,3,6,9,2] } 7 | 8 | context "with an array" do 9 | 10 | it "responds to all statistics methods" do 11 | DescriptiveStatistics.instance_methods.each do |method| 12 | expect(subject).respond_to? method 13 | end 14 | end 15 | 16 | it "calculates the number" do 17 | expect(subject.number).to eql(11.0) 18 | end 19 | 20 | it "calculates the sum" do 21 | expect(subject.sum).to eql(54.0) 22 | end 23 | 24 | it "calculates the mean" do 25 | expect(subject.mean).to eql(4.909090909090909) 26 | end 27 | 28 | it "calculates the median" do 29 | expect(subject.median).to eql(5.0) 30 | end 31 | 32 | it "calculates the variance" do 33 | expect(subject.variance).to eql(7.7190082644628095) 34 | end 35 | 36 | it "calculates the standard_deviation" do 37 | expect(subject.standard_deviation).to eql(2.778310325442932) 38 | end 39 | 40 | it "calculates the percentile" do 41 | expect(subject.percentile(30)).to eql(3.0) 42 | expect(subject.percentile(50)).to eql(5.0) 43 | expect(subject.percentile(70)).to eql(6.0) 44 | end 45 | 46 | it "calculates the same value for the 50th percentile and median" do 47 | expect(subject.percentile(50)).to eql(subject.median) 48 | end 49 | 50 | it "calculates the mode" do 51 | expect(subject.mode).to eql(2) 52 | end 53 | 54 | it "calculates the range" do 55 | expect(subject.range).to eql(8.0) 56 | end 57 | 58 | it "calculates the percentile rank" do 59 | expect(subject.percentile_rank(8)).to eql(81.81818181818183) 60 | end 61 | 62 | end 63 | 64 | end -------------------------------------------------------------------------------- /spec/monkeypatch/set_spec.rb: -------------------------------------------------------------------------------- 1 | require 'monkeypatch/spec_helper' 2 | 3 | describe "DescriptiveStatistics" do 4 | require 'descriptive_statistics' 5 | 6 | subject { Set.new([2,6,9,3,5,1,8,3,6,9,2]) } 7 | 8 | context "with a set" do 9 | 10 | it "responds to all statistics methods" do 11 | DescriptiveStatistics.instance_methods.each do |method| 12 | expect(subject).respond_to? method 13 | end 14 | end 15 | 16 | it "calculates the number" do 17 | expect(subject.number).to eql(7.0) 18 | end 19 | 20 | it "calculates the sum" do 21 | expect(subject.sum).to eql(34.0) 22 | end 23 | 24 | it "calculates the mean" do 25 | expect(subject.mean).to eql(4.857142857142857) 26 | end 27 | 28 | it "calculates the median" do 29 | expect(subject.median).to eql(5.0) 30 | end 31 | 32 | it "calculates the variance" do 33 | expect(subject.variance).to eql(7.836734693877552) 34 | end 35 | 36 | it "calculates the standard_deviation" do 37 | expect(subject.standard_deviation).to eql(2.799416848895061) 38 | end 39 | 40 | it "calculates the percentile" do 41 | expect(subject.percentile(30)).to eql(2.8) 42 | expect(subject.percentile(50)).to eql(5.0) 43 | expect(subject.percentile(70)).to eql(6.399999999999999) 44 | end 45 | 46 | it "calculates the same value for the 50th percentile and median" do 47 | expect(subject.percentile(50)).to eql(subject.median) 48 | end 49 | 50 | it "calculates the mode" do 51 | expect(subject.mode).to eql(2) 52 | end 53 | 54 | it "calculates the range" do 55 | expect(subject.range).to eql(8.0) 56 | end 57 | 58 | it "calculates the percentile rank" do 59 | expect(subject.percentile_rank(8)).to eql(85.71428571428571) 60 | end 61 | 62 | end 63 | 64 | end -------------------------------------------------------------------------------- /spec/monkeypatch/hash_spec.rb: -------------------------------------------------------------------------------- 1 | require 'monkeypatch/spec_helper' 2 | 3 | describe "DescriptiveStatistics" do 4 | require 'descriptive_statistics' 5 | 6 | subject { {:a=>2,:b=>6,:c=>9,:d=>3,:e=>5,:f=>1,:g=>8,:h=>3,:i=>6,:j=>9,:k=>2} } 7 | 8 | context "with a hash" do 9 | 10 | it "responds to all statistics methods" do 11 | DescriptiveStatistics.instance_methods.each do |method| 12 | expect(subject).respond_to? method 13 | end 14 | end 15 | 16 | it "calculates the number" do 17 | expect(subject.number).to eql(11.0) 18 | end 19 | 20 | it "calculates the sum" do 21 | expect(subject.sum).to eql(54.0) 22 | end 23 | 24 | it "calculates the mean" do 25 | expect(subject.mean).to eql(4.909090909090909) 26 | end 27 | 28 | it "calculates the median" do 29 | expect(subject.median).to eql(5.0) 30 | end 31 | 32 | it "calculates the variance" do 33 | expect(subject.variance).to eql(7.7190082644628095) 34 | end 35 | 36 | it "calculates the standard_deviation" do 37 | expect(subject.standard_deviation).to eql(2.778310325442932) 38 | end 39 | 40 | it "calculates the percentile" do 41 | expect(subject.percentile(30)).to eql(3.0) 42 | expect(subject.percentile(50)).to eql(5.0) 43 | expect(subject.percentile(70)).to eql(6.0) 44 | end 45 | 46 | it "calculates the same value for the 50th percentile and median" do 47 | expect(subject.percentile(50)).to eql(subject.median) 48 | end 49 | 50 | it "calculates the mode" do 51 | expect(subject.mode).to eql(2) 52 | end 53 | 54 | it "calculates the range" do 55 | expect(subject.range).to eql(8.0) 56 | end 57 | 58 | it "calculates the percentile rank" do 59 | expect(subject.percentile_rank(8)).to eql(81.81818181818183) 60 | end 61 | 62 | end 63 | 64 | end -------------------------------------------------------------------------------- /spec/safe/extend_spec.rb: -------------------------------------------------------------------------------- 1 | require 'safe/spec_helper' 2 | 3 | describe "DescriptiveStatistics" do 4 | require 'descriptive_statistics/safe' 5 | 6 | subject { [2,6,9,3,5,1,8,3,6,9,2] } 7 | 8 | it "is extendable" do 9 | subject.extend(DescriptiveStatistics) 10 | DescriptiveStatistics.instance_methods.each do |method| 11 | expect(subject).respond_to? method 12 | end 13 | end 14 | 15 | context "is extended" do 16 | 17 | before do 18 | subject.extend(DescriptiveStatistics) 19 | end 20 | 21 | it "calculates the number" do 22 | expect(subject.number).to eql(11.0) 23 | end 24 | 25 | it "calculates the sum" do 26 | expect(subject.sum).to eql(54.0) 27 | end 28 | 29 | it "calculates the mean" do 30 | expect(subject.mean).to eql(4.909090909090909) 31 | end 32 | 33 | it "calculates the median" do 34 | expect(subject.median).to eql(5.0) 35 | end 36 | 37 | it "calculates the variance" do 38 | expect(subject.variance).to eql(7.7190082644628095) 39 | end 40 | 41 | it "calculates the standard_deviation" do 42 | expect(subject.standard_deviation).to eql(2.778310325442932) 43 | end 44 | 45 | it "calculates the percentile" do 46 | expect(subject.percentile(30)).to eql(3.0) 47 | expect(subject.percentile(50)).to eql(5.0) 48 | expect(subject.percentile(70)).to eql(6.0) 49 | end 50 | 51 | it "calculates the same value for the 50th percentile and median" do 52 | expect(subject.percentile(50)).to eql(subject.median) 53 | end 54 | 55 | it "calculates the mode" do 56 | expect(subject.mode).to eql(2) 57 | end 58 | 59 | it "calculates the range" do 60 | expect(subject.range).to eql(8.0) 61 | end 62 | 63 | it "calculates the percentile rank" do 64 | expect(subject.percentile_rank(8)).to eql(81.81818181818183) 65 | end 66 | 67 | end 68 | 69 | end -------------------------------------------------------------------------------- /spec/monkeypatch/object_spec.rb: -------------------------------------------------------------------------------- 1 | require 'monkeypatch/spec_helper' 2 | require 'ostruct' 3 | 4 | describe "DescriptiveStatistics" do 5 | require 'descriptive_statistics' 6 | 7 | subject { 8 | [ 9 | OpenStruct.new( price: 2.5, quantity: 2 ), 10 | OpenStruct.new( price: 5.1, quantity: 9 ), 11 | OpenStruct.new( price: 5.7, quantity: 4 ), 12 | OpenStruct.new( price: 0.5, quantity: 10 ) 13 | ] 14 | } 15 | 16 | context "with an array of objects" do 17 | 18 | context "called with a method turned block" do 19 | 20 | it "calculates the number" do 21 | expect(subject.number(&:price)).to eql(4.0) 22 | end 23 | 24 | it "calculates the sum" do 25 | expect(subject.sum(&:price)).to eql(13.8) 26 | end 27 | 28 | it "calculates the mean" do 29 | expect(subject.mean(&:price)).to eql(3.45) 30 | end 31 | 32 | it "calculates the median" do 33 | expect(subject.median(&:price)).to eql(3.8) 34 | end 35 | 36 | it "calculates the variance" do 37 | expect(subject.variance(&:price)).to eql(4.3475) 38 | end 39 | 40 | it "calculates the standard_deviation" do 41 | expect(subject.standard_deviation(&:price)).to eql(2.0850659461993044) 42 | end 43 | 44 | it "calculates the percentile" do 45 | expect(subject.percentile(30, &:price)).to eql(2.3) 46 | expect(subject.percentile(50, &:price)).to eql(3.8) 47 | expect(subject.percentile(70, &:price)).to eql(5.159999999999999) 48 | end 49 | 50 | it "calculates the same value for the 50th percentile and median" do 51 | expect(subject.percentile(50, &:price)).to eql(subject.median(&:price)) 52 | end 53 | 54 | it "calculates the mode" do 55 | expect(subject.mode(&:price)).to eql(2.5) 56 | end 57 | 58 | it "calculates the range" do 59 | expect(subject.range(&:price)).to eql(5.2) 60 | end 61 | 62 | it "calculates the percentile rank" do 63 | expect(subject.percentile_rank(8, &:price)).to eql(100.0) 64 | end 65 | 66 | end 67 | 68 | context "called with a block" do 69 | 70 | it "calculates the number" do 71 | expect(subject.number{|v| v.price * v.quantity}).to eql(4.0) 72 | end 73 | 74 | it "calculates the sum" do 75 | expect(subject.sum{|v| v.price * v.quantity}).to eql(78.7) 76 | end 77 | 78 | it "calculates the mean" do 79 | expect(subject.mean{|v| v.price * v.quantity}).to eql(19.675) 80 | end 81 | 82 | it "calculates the median" do 83 | expect(subject.median{|v| v.price * v.quantity}).to eql(13.9) 84 | end 85 | 86 | it "calculates the variance" do 87 | expect(subject.variance{|v| v.price * v.quantity}).to eql(282.056875) 88 | end 89 | 90 | it "calculates the standard_deviation" do 91 | expect(subject.standard_deviation{|v| v.price * v.quantity}).to eql(16.79454896685231) 92 | end 93 | 94 | it "calculates the percentile" do 95 | expect(subject.percentile(30){|v| v.price * v.quantity}).to eql(5.0) 96 | expect(subject.percentile(50){|v| v.price * v.quantity}).to eql(13.9) 97 | expect(subject.percentile(70){|v| v.price * v.quantity}).to eql(25.109999999999992) 98 | end 99 | 100 | it "calculates the same value for the 50th percentile and median" do 101 | expect(subject.percentile(50){|v| v.price * v.quantity}).to eql(subject.median{|v| v.price * v.quantity}) 102 | end 103 | 104 | it "calculates the mode" do 105 | expect(subject.mode{|v| v.price * v.quantity}).to eql(5.0) 106 | end 107 | 108 | it "calculates the range" do 109 | expect(subject.range{|v| v.price * v.quantity}).to eql(40.9) 110 | end 111 | 112 | it "calculates the percentile rank" do 113 | expect(subject.percentile_rank(8){|v| v.price * v.quantity}).to eql(50.0) 114 | end 115 | 116 | end 117 | end 118 | 119 | end -------------------------------------------------------------------------------- /test/test.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | require 'minitest' 3 | require 'csv' 4 | require './lib/descriptive_statistics' 5 | 6 | SimpleCov.command_name 'minitest' 7 | 8 | class TestData < MiniTest::Unit::TestCase 9 | 10 | def setup 11 | @data = [] 12 | CSV.foreach("test/testdata.csv") do |row| 13 | @data.push row.map(&:to_f) 14 | end 15 | end 16 | 17 | def test_sum 18 | @data.each do |test_case| 19 | assert_equal test_case[0,10].sum.round(6), test_case[10].round(6) 20 | end 21 | end 22 | 23 | def test_mean 24 | @data.each do |test_case| 25 | assert_equal test_case[0,10].mean.round(6), test_case[11].round(6) 26 | end 27 | end 28 | 29 | def test_median 30 | @data.each do |test_case| 31 | assert_equal test_case[0,10].median.round(6), test_case[12].round(6) 32 | end 33 | end 34 | 35 | def test_variance 36 | @data.each do |test_case| 37 | assert_equal test_case[0,10].variance.round(6), test_case[13].round(6) 38 | end 39 | end 40 | 41 | def test_standard_deviation 42 | @data.each do |test_case| 43 | assert_equal test_case[0,10].standard_deviation.round(6), test_case[14].round(6) 44 | end 45 | end 46 | 47 | def test_percentile 48 | @data.each do |test_case| 49 | assert_equal test_case[0,10].percentile(0).round(6), test_case[15].round(6) 50 | assert_equal test_case[0,10].percentile(10).round(6), test_case[16].round(6) 51 | assert_equal test_case[0,10].percentile(20).round(6), test_case[17].round(6) 52 | assert_equal test_case[0,10].percentile(30).round(6), test_case[18].round(6) 53 | assert_equal test_case[0,10].percentile(40).round(6), test_case[19].round(6) 54 | assert_equal test_case[0,10].percentile(50).round(6), test_case[20].round(6) 55 | assert_equal test_case[0,10].percentile(60).round(6), test_case[21].round(6) 56 | assert_equal test_case[0,10].percentile(70).round(6), test_case[22].round(6) 57 | assert_equal test_case[0,10].percentile(80).round(6), test_case[23].round(6) 58 | assert_equal test_case[0,10].percentile(90).round(6), test_case[24].round(6) 59 | assert_equal test_case[0,10].percentile(100).round(6), test_case[25].round(6) 60 | end 61 | end 62 | 63 | def test_percentile_rank 64 | @data.each do |test_case| 65 | assert_equal test_case[0,10].percentile_rank(50).round(6), test_case[26].round(6) 66 | end 67 | end 68 | 69 | def test_percentile_rank_for_smallest_number 70 | assert_equal [2,3,4,5,6,7,8,9,10,11].percentile_rank(1), 0 71 | assert_equal [2,3,4,5,6,7,8,9,10,11].percentile_rank(2), 10 72 | end 73 | 74 | def test_mode 75 | assert_equal [1,3,6,9,4,5,2,3,4,1,6,7,8,3,2,3,5,7,8,5,6,5,6,5,4,5,5,5].mode, 5 76 | end 77 | 78 | def test_range 79 | assert_equal [17, 5, 3, 23, 33, 30, 45, 37].range, 42 80 | assert_equal [].range, nil 81 | assert_equal [1, 1.0].range, 0 82 | end 83 | 84 | def test_descriptive_statistics 85 | @data.each do |test_case| 86 | stat = test_case[0, 10].descriptive_statistics 87 | assert_equal test_case[0, 10].sum, stat[:sum] 88 | assert_equal test_case[0, 10].mean, stat[:mean] 89 | assert_equal test_case[0, 10].median, stat[:median] 90 | assert_equal test_case[0, 10].variance, stat[:variance] 91 | assert_equal test_case[0, 10].standard_deviation, stat[:standard_deviation] 92 | assert_equal test_case[0, 10].mode, stat[:mode] 93 | assert_equal test_case[0, 10].range, stat[:range] 94 | assert_equal test_case[0, 10].min, stat[:min] 95 | assert_equal test_case[0, 10].max, stat[:max] 96 | assert_equal test_case[0, 10].percentile(25), stat[:q1] 97 | assert_equal test_case[0, 10].percentile(50), stat[:q2] 98 | assert_equal test_case[0, 10].percentile(75), stat[:q3] 99 | end 100 | end 101 | 102 | def test_median_is_percentile50 103 | @data.each do |test_case| 104 | assert_equal test_case[0, 10].median, test_case[0, 10].percentile(50) 105 | end 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /spec/monkeypatch/empty_collection_spec.rb: -------------------------------------------------------------------------------- 1 | require 'monkeypatch/spec_helper' 2 | 3 | describe "DescriptiveStatistics" do 4 | require 'descriptive_statistics' 5 | 6 | subject { [] } 7 | 8 | context "with a default of nil" do 9 | 10 | before do 11 | DescriptiveStatistics.empty_collection_default_value = nil 12 | end 13 | 14 | it "calculates the number" do 15 | expect(subject.number).to eql(0.0) 16 | end 17 | 18 | it "calculates the sum" do 19 | expect(subject.sum).to eql(nil) 20 | end 21 | 22 | it "calculates the mean" do 23 | expect(subject.mean).to eql(nil) 24 | end 25 | 26 | it "calculates the median" do 27 | expect(subject.median).to eql(nil) 28 | end 29 | 30 | it "calculates the variance" do 31 | expect(subject.variance).to eql(nil) 32 | end 33 | 34 | it "calculates the standard_deviation" do 35 | expect(subject.standard_deviation).to eql(nil) 36 | end 37 | 38 | it "calculates the percentile" do 39 | expect(subject.percentile(30)).to eql(nil) 40 | expect(subject.percentile(50)).to eql(nil) 41 | expect(subject.percentile(70)).to eql(nil) 42 | end 43 | 44 | it "calculates the same value for the 50th percentile and median" do 45 | expect(subject.percentile(50)).to eql(subject.median) 46 | end 47 | 48 | it "does not calculate a mode" do 49 | expect(subject.mode).to eql(nil) 50 | end 51 | 52 | it "calculates the range" do 53 | expect(subject.range).to eql(nil) 54 | end 55 | 56 | it "calculates the percentile rank" do 57 | expect(subject.percentile_rank(8)).to eql(nil) 58 | end 59 | 60 | end 61 | 62 | context "with a default of 0.0" do 63 | 64 | before do 65 | DescriptiveStatistics.empty_collection_default_value = 0.0 66 | end 67 | 68 | it "sets a default" do 69 | expect(DescriptiveStatistics.empty_collection_default_value).to eql(0.0) 70 | end 71 | 72 | it "calculates the number" do 73 | expect(subject.number).to eql(0.0) 74 | end 75 | 76 | it "calculates the sum" do 77 | expect(subject.sum).to eql(0.0) 78 | end 79 | 80 | it "calculates the mean" do 81 | expect(subject.mean).to eql(0.0) 82 | end 83 | 84 | it "calculates the median" do 85 | expect(subject.median).to eql(0.0) 86 | end 87 | 88 | it "calculates the variance" do 89 | expect(subject.variance).to eql(0.0) 90 | end 91 | 92 | it "calculates the standard_deviation" do 93 | expect(subject.standard_deviation).to eql(0.0) 94 | end 95 | 96 | it "calculates the percentile" do 97 | expect(subject.percentile(30)).to eql(0.0) 98 | expect(subject.percentile(50)).to eql(0.0) 99 | expect(subject.percentile(70)).to eql(0.0) 100 | end 101 | 102 | it "calculates the same value for the 50th percentile and median" do 103 | expect(subject.percentile(50)).to eql(subject.median) 104 | end 105 | 106 | it "does not calculate a mode" do 107 | expect(subject.mode).to eql(nil) 108 | end 109 | 110 | it "calculates the range" do 111 | expect(subject.range).to eql(0.0) 112 | end 113 | 114 | it "calculates the percentile rank" do 115 | expect(subject.percentile_rank(8)).to eql(0.0) 116 | end 117 | 118 | end 119 | 120 | context "with a default of 0.0 only for sum" do 121 | 122 | before do 123 | DescriptiveStatistics.empty_collection_default_value = nil 124 | DescriptiveStatistics.sum_empty_collection_default_value = 0.0 125 | end 126 | 127 | it "calculates the number" do 128 | expect(subject.number).to eql(0.0) 129 | end 130 | 131 | it "calculates the sum" do 132 | expect(subject.sum).to eql(0.0) 133 | end 134 | 135 | it "calculates the mean" do 136 | expect(subject.mean).to eql(nil) 137 | end 138 | 139 | it "calculates the median" do 140 | expect(subject.median).to eql(nil) 141 | end 142 | 143 | it "calculates the variance" do 144 | expect(subject.variance).to eql(nil) 145 | end 146 | 147 | it "calculates the standard_deviation" do 148 | expect(subject.standard_deviation).to eql(nil) 149 | end 150 | 151 | it "calculates the percentile" do 152 | expect(subject.percentile(30)).to eql(nil) 153 | expect(subject.percentile(50)).to eql(nil) 154 | expect(subject.percentile(70)).to eql(nil) 155 | end 156 | 157 | it "calculates the same value for the 50th percentile and median" do 158 | expect(subject.percentile(50)).to eql(subject.median) 159 | end 160 | 161 | it "does not calculate a mode" do 162 | expect(subject.mode).to eql(nil) 163 | end 164 | 165 | it "calculates the range" do 166 | expect(subject.range).to eql(nil) 167 | end 168 | 169 | it "calculates the percentile rank" do 170 | expect(subject.percentile_rank(8)).to eql(nil) 171 | end 172 | 173 | end 174 | 175 | context "with a default of 0.0 only for variance" do 176 | 177 | before do 178 | DescriptiveStatistics.empty_collection_default_value = nil 179 | DescriptiveStatistics.variance_empty_collection_default_value = 0.0 180 | end 181 | 182 | it "calculates the number" do 183 | expect(subject.number).to eql(0.0) 184 | end 185 | 186 | it "calculates the sum" do 187 | expect(subject.sum).to eql(nil) 188 | end 189 | 190 | it "calculates the mean" do 191 | expect(subject.mean).to eql(nil) 192 | end 193 | 194 | it "calculates the median" do 195 | expect(subject.median).to eql(nil) 196 | end 197 | 198 | it "calculates the variance" do 199 | expect(subject.variance).to eql(0.0) 200 | end 201 | 202 | it "calculates the standard_deviation" do 203 | expect(subject.standard_deviation).to eql(nil) 204 | end 205 | 206 | it "calculates the percentile" do 207 | expect(subject.percentile(30)).to eql(nil) 208 | expect(subject.percentile(50)).to eql(nil) 209 | expect(subject.percentile(70)).to eql(nil) 210 | end 211 | 212 | it "calculates the same value for the 50th percentile and median" do 213 | expect(subject.percentile(50)).to eql(subject.median) 214 | end 215 | 216 | it "does not calculate a mode" do 217 | expect(subject.mode).to eql(nil) 218 | end 219 | 220 | it "calculates the range" do 221 | expect(subject.range).to eql(nil) 222 | end 223 | 224 | it "calculates the percentile rank" do 225 | expect(subject.percentile_rank(8)).to eql(nil) 226 | end 227 | 228 | end 229 | 230 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Descriptive Statistics 2 | =============== 3 | [![Gem Version](https://badge.fury.io/rb/descriptive_statistics.svg)](http://badge.fury.io/rb/descriptive_statistics) 4 | [![Build Status](https://travis-ci.org/thirtysixthspan/descriptive_statistics.svg?branch=master)](https://travis-ci.org/thirtysixthspan/descriptive_statistics) 5 | 6 | Overview 7 | -------- 8 | 9 | This gem adds methods to the Enumerable module to allow easy calculation of basic 10 | descriptive statistics of Numeric sample data in collections that have included Enumerable such as Array, Hash, Set, and Range. The statistics that can be calculated are: 11 | * Number 12 | * Sum 13 | * Mean 14 | * Median 15 | * Mode 16 | * Variance 17 | * Standard Deviation 18 | * Percentile 19 | * Percentile Rank 20 | * Descriptive Statistics 21 | * Quartiles 22 | 23 | 24 | When requiring DescriptiveStatistics, the Enumerable module is monkey patched so 25 | that the statistical methods are available on any instance of a class that has included Enumerable. For example with an Array: 26 | ```ruby 27 | require 'descriptive_statistics' 28 | data = [2,6,9,3,5,1,8,3,6,9,2] 29 | # => [2, 6, 9, 3, 5, 1, 8, 3, 6, 9, 2] 30 | data.number 31 | # => 11.0 32 | data.sum 33 | # => 54.0 34 | data.mean 35 | # => 4.909090909090909 36 | data.median 37 | # => 5.0 38 | data.variance 39 | # => 7.7190082644628095 40 | data.standard_deviation 41 | # => 2.778310325442932 42 | data.percentile(30) 43 | # => 3.0 44 | data.percentile(70) 45 | # => 6.0 46 | data.percentile_rank(8) 47 | # => 81.81818181818183 48 | data.mode 49 | # => 2 50 | data.range 51 | # => 8 52 | data.descriptive_statistics 53 | # => {:number=>11.0, 54 | :sum=>54, 55 | :variance=>7.7190082644628095, 56 | :standard_deviation=>2.778310325442932, 57 | :min=>1, 58 | :max=>9, 59 | :mean=>4.909090909090909, 60 | :mode=>2, 61 | :median=>5.0, 62 | :range=>8.0, 63 | :q1=>2.5, 64 | :q2=>5.0, 65 | :q3=>7.0} 66 | ``` 67 | 68 | and with other types of objects: 69 | ```ruby 70 | require 'set' 71 | require 'descriptive_statistics' 72 | {:a=>1, :b=>2, :c=>3, :d=>4, :e=>5}.mean #Hash 73 | # => 3.0 74 | Set.new([1,2,3,4,5]).mean #Set 75 | # => 3.0 76 | (1..5).mean #Range 77 | # => 3.0 78 | ``` 79 | 80 | including instances of your own classes, when an `each` method is provided that 81 | creates an Enumerator over the sample data to be operated upon: 82 | ```ruby 83 | class Foo 84 | include Enumerable 85 | attr_accessor :bar, :baz, :bat 86 | 87 | def each 88 | [@bar, @baz, @bat].each 89 | end 90 | end 91 | 92 | foo = Foo.new 93 | foo.bar = 1 94 | foo.baz = 2 95 | foo.bat = 3 96 | foo.mean 97 | # => 2.0 98 | 99 | ``` 100 | 101 | or: 102 | ```ruby 103 | class Foo 104 | include Enumerable 105 | attr_accessor :bar, :baz, :bat 106 | 107 | def each 108 | Enumerator.new do |y| 109 | y << @bar 110 | y << @baz 111 | y << @bat 112 | end 113 | end 114 | end 115 | 116 | foo = Foo.new 117 | foo.bar = 1 118 | foo.baz = 2 119 | foo.bat = 3 120 | foo.mean 121 | # => 2.0 122 | ``` 123 | 124 | and even Structs: 125 | ```ruby 126 | Scores = Struct.new(:sally, :john, :peter) 127 | bowling = Scores.new 128 | bowling.sally = 203 129 | bowling.john = 134 130 | bowling.peter = 233 131 | bowling.mean 132 | # => 190.0 133 | ``` 134 | 135 | All methods optionally take blocks that operate on object values. For example: 136 | ```ruby 137 | require 'descriptive_statistics' 138 | LineItem = Struct.new(:price, :quantity) 139 | cart = [ LineItem.new(2.50, 2), LineItem.new(5.10, 9), LineItem.new(4.00, 5) ] 140 | total_items = cart.sum(&:quantity) 141 | # => 16 142 | total_price = cart.sum{ |i| i.price * i.quantity } 143 | # => 70.9 144 | ``` 145 | 146 | Note that you can extend DescriptiveStatistics on individual objects by 147 | requiring DescriptiveStatistics safely, thus avoiding the monkey patch. For example: 148 | ```ruby 149 | require 'descriptive_statistics/safe' 150 | data = [2,6,9,3,5,1,8,3,6,9,2] 151 | # => [2, 6, 9, 3, 5, 1, 8, 3, 6, 9, 2] 152 | data.extend(DescriptiveStatistics) 153 | # => [2, 6, 9, 3, 5, 1, 8, 3, 6, 9, 2] 154 | data.number 155 | # => 11.0 156 | data.sum 157 | # => 54 158 | ``` 159 | 160 | Or, if you prefer leaving your collection pristine, you can create a 161 | Stats object that references your collection: 162 | ```ruby 163 | require 'descriptive_statistics/safe' 164 | data = [1, 2, 3, 4, 5, 1] 165 | # => [1, 2, 3, 4, 5, 1] 166 | stats = DescriptiveStatistics::Stats.new(data) 167 | # => [1, 2, 3, 4, 5, 1] 168 | stats.class 169 | # => DescriptiveStatistics::Stats 170 | stats.mean 171 | # => 2.6666666666666665 172 | stats.median 173 | # => 2.5 174 | stats.mode 175 | # => 1 176 | data << 2 177 | # => [1, 2, 3, 4, 5, 1, 2] 178 | data << 2 179 | # => [1, 2, 3, 4, 5, 1, 2, 2] 180 | stats.mode 181 | # => 2 182 | ``` 183 | 184 | Or you call the statistical methods directly: 185 | ```ruby 186 | require 'descriptive_statistics/safe' 187 | # => true 188 | DescriptiveStatistics.mean([1,2,3,4,5]) 189 | # => 3.0 190 | DescriptiveStatistics.mode([1,2,3,4,5]) 191 | # => 1 192 | DescriptiveStatistics.variance([1,2,3,4,5]) 193 | # => 2.0 194 | ``` 195 | 196 | Or you can use [Refinements](http://www.ruby-doc.org/core/doc/syntax/refinements_rdoc.html) (available in Ruby >= 2.1) to augment any class that mixes in the Enumerable module. Refinements are lexically scoped and so the statistical methods will only be available in the file where they are used. Note that the lexical scope can be limited to a Class or Module, but only applies to code in that file. This approach provides a great deal of protection against introducing conflicting modifications to Enumerable while retaining the convenience of the monkey patch approach. 197 | ```ruby 198 | require 'descriptive_statistics/refinement' 199 | 200 | class SomeServiceClass 201 | using DescriptiveStatistics::Refinement.new(Array) 202 | 203 | def self.calculate_something(array) 204 | array.standard_deviation 205 | end 206 | end 207 | 208 | [1,2,3].standard_deviation 209 | # => NoMethodError: undefined method `standard_deviation' for [1, 2, 3]:Array 210 | 211 | SomeServiceClass.calculate_something([1,2,3]) 212 | #=> 0.816496580927726 213 | ``` 214 | 215 | 216 | Ruby on Rails 217 | ------------- 218 | 219 | To use DescriptiveStatistics with Ruby on Rails add DescriptiveStatistics to your Gemfile, requiring the safe extension. 220 | ```ruby 221 | source 'https://rubygems.org' 222 | 223 | gem 'rails', '4.1.7' 224 | gem 'descriptive_statistics', '~> 2.4.0', :require => 'descriptive_statistics/safe' 225 | ``` 226 | Then after a `bundle install`, you can extend DescriptiveStatistics on an individual collection and call the statistical methods as needed. 227 | ```ruby 228 | users = User.all.extend(DescriptiveStatistics) 229 | mean_age = users.mean(&:age) # => 19.428571428571427 230 | mean_age_in_dog_years = users.mean { |user| user.age / 7.0 } # => 2.7755102040816326 231 | ``` 232 | 233 | Notes 234 | ----- 235 | * All methods return a Float object except for `mode`, which will return a Numeric object from the collection. `mode` will always return nil for empty collections. 236 | * All methods return nil when the collection is empty, except for `number`, which returns 0.0. This is a different behavior than [ActiveSupport's Enumerable monkey patch of sum](http://apidock.com/rails/Enumerable/sum), which by deafult returns the Fixnum 0 for empty collections. You can change this behavior by specifying the default value returned for empty collections all at once: 237 | ```ruby 238 | require 'descriptive_statistics' 239 | [].mean 240 | # => nil 241 | [].sum 242 | # => nil 243 | DescriptiveStatistics.empty_collection_default_value = 0.0 244 | # => 0.0 245 | [].mean 246 | # => 0.0 247 | [].sum 248 | # => 0.0 249 | ``` 250 | or one at a time: 251 | ```ruby 252 | require 'descriptive_statistics' 253 | [].mean 254 | # => nil 255 | [].sum 256 | # => nil 257 | DescriptiveStatistics.sum_empty_collection_default_value = 0.0 258 | # => 0.0 259 | [].mean 260 | # => nil 261 | [].sum 262 | # => 0.0 263 | DescriptiveStatistics.mean_empty_collection_default_value = 0.0 264 | # => 0.0 265 | [].mean 266 | # => 0.0 267 | [].sum 268 | # => 0.0 269 | ``` 270 | 271 | * The scope of this gem covers [Descriptive Statistics](http://en.wikipedia.org/wiki/Descriptive_statistics) and not Inferential Statistics. From wikipedia: 272 | 273 | > Descriptive statistics is the discipline of quantitatively describing the main features of a collection of information, or the quantitative description itself. Descriptive statistics are distinguished from inferential statistics, in that descriptive statistics aim to summarize a sample, rather than use the data to learn about the population that the sample of data is thought to represent. 274 | 275 | Thus, all statistics calculated herein describe only the values in the collection. Where this makes a practical difference is in the calculation of variance (and thus the standard deviation which is derived from variance). We use the [population variance](http://en.wikipedia.org/wiki/Variance#Population_variance) to calculate the variance of the values in the collection. If the values in your collection represent a sampling from a larger population of values, and your goal is to estimate the population variance from your sample, you should use the inferential statistic, [sample variance](http://en.wikipedia.org/wiki/Variance#Sample_variance). However, the calculation of the sample variance is outside the scope of this gem's functionality. 276 | 277 | 278 | Ports 279 | ----- 280 | [Javascript](http://github.com/FGRibreau/descriptive_statistics) 281 | 282 | [Python](http://github.com/gleicon/py_descriptive_statistics) 283 | 284 | [Go](https://github.com/gleicon/go-descriptive-statistics) 285 | 286 | [Elixir](https://github.com/pusewicz/descriptive_statistics) 287 | 288 | [Clojure](https://github.com/nickmcdonnough/descriptivestatistics) 289 | 290 | License 291 | ------- 292 | Copyright (c) 2010-2014 293 | Derrick Parkhurst (derrick.parkhurst@gmail.com), 294 | Gregory Brown (gregory.t.brown@gmail.com), 295 | Daniel Farrell (danielfarrell76@gmail.com), 296 | Graham Malmgren, 297 | Guy Shechter, 298 | Charlie Egan (charlieegan3@googlemail.com) 299 | 300 | Permission is hereby granted, free of charge, to any person obtaining a copy 301 | of this software and associated documentation files (the "Software"), to deal 302 | in the Software without restriction, including without limitation the rights 303 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 304 | copies of the Software, and to permit persons to whom the Software is 305 | furnished to do so, subject to the following conditions: 306 | 307 | The above copyright notice and this permission notice shall be included in 308 | all copies or substantial portions of the Software. 309 | 310 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 311 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 312 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 313 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 314 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 315 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 316 | THE SOFTWARE. 317 | 318 | -------------------------------------------------------------------------------- /test/testdata.csv: -------------------------------------------------------------------------------- 1 | 20.2079534531,76.868482586,44.0650910139,21.3175462559,52.5786303915,14.5135614555,18.0975256022,44.9073698837,47.3898619879,67.9193196353,407.865342265,40.7865342265,44.4862304488,425.6062421892,20.6302264212,14.5135614555,17.7391291875,19.7858678829,20.984668415,34.9660731107,44.4862304488,45.9003667254,48.946492509,55.6467682403,68.8142359303,76.868482586,70.0 2 | 35.0738437846,28.5874244291,1.985015627,84.0000894852,89.041401539,29.4274967164,65.1129378937,58.1659873016,81.4108015504,20.0056413189,492.8106396459,49.2810639646,46.6199155431,826.6407823658,28.7513614002,1.985015627,18.2035787497,26.8710678071,29.1754750302,32.8153049573,46.6199155431,60.9447675385,70.0022969907,81.9286591373,84.5042206906,89.041401539,50.0 3 | 86.0927627422,68.842604151,62.157658441,89.5046351012,18.8363627996,87.9375424702,53.1476892997,95.7490334753,71.3422942441,34.8138025962,668.4243853204,66.842438532,70.0924491975,572.8904289018,23.9351295986,18.8363627996,33.2160586165,49.480911959,59.4546676986,66.168625867,70.0924491975,77.2424816433,86.6461966606,88.2509609964,90.1290749386,95.7490334753,20.0 4 | 61.0640817787,37.6485045534,83.7659041863,4.4028460979,82.749720756,66.2769843824,53.2144752797,54.0063686203,49.939918844,15.5805064831,508.6493109819,50.8649310982,53.61042195,603.5302431545,24.5668525284,4.4028460979,14.4627404446,33.2349049393,46.2524945568,51.9046527054,53.61042195,56.8294538837,62.6279525599,69.5715316571,82.851339099,83.7659041863,40.0 5 | 4.0229333565,58.4163229913,53.5523145925,98.6344025936,74.5573930908,17.2770340461,75.6864419207,85.0378243718,40.2164024301,61.5725832526,568.9736526459,56.8973652646,59.9944531219,787.7856684544,28.067519813,4.0229333565,15.9516239772,35.6285287533,49.5515409438,56.4707196318,59.9944531219,66.7665071879,74.8961077398,77.5567184109,86.397482194,98.6344025936,30.0 6 | 13.4409535676,3.1409711577,53.7517756689,48.4051625244,86.10626054,75.1113484614,62.0299534872,30.7148828637,17.0759572182,50.4072077107,440.1844731998,44.01844732,49.4061851176,672.6197869505,25.9349144389,3.1409711577,12.4109553266,16.3489564881,26.62320517,41.3290506601,49.4061851176,51.745034894,56.2352290144,64.646232482,76.2108396692,86.10626054,50.0 7 | 2.106716251,90.3022720013,6.0940884519,45.5669269431,87.9215690307,96.4341778774,37.4287451152,25.0365303364,95.6130996346,93.9403876662,580.4445133079,58.0444513308,66.7442479869,1360.4991056653,36.8849441597,2.106716251,5.6953512318,21.2480419595,33.7110806815,42.311654212,66.7442479869,88.873850219,91.3937067008,94.2749300599,95.6952074589,96.4341778774,50.0 8 | 7.5800470542,10.2862322703,23.3446593862,43.3414899278,97.8113875724,69.2283398472,64.9194436613,88.965559192,69.3663077895,56.0962414369,530.9397081379,53.0939708138,60.5078425491,884.4532615107,29.739758935,7.5800470542,10.0156137487,20.732973963,37.3424407654,50.9943408333,60.5078425491,66.6430021357,69.2697302299,73.28615807,89.85014203,97.8113875724,40.0 9 | 97.8508994915,80.7058474049,53.6904865876,40.4215564486,15.9916954581,20.7083533052,1.0901243426,44.1540362313,39.5355603192,9.5302689821,403.678828571,40.3678828571,39.9785583839,859.8367312184,29.3229727555,1.0901243426,8.6862545181,14.6994101629,19.2933559511,32.0046775136,39.9785583839,41.9145483617,47.0149713382,59.093558751,82.4203526136,97.8508994915,70.0 10 | 80.0685187336,23.1779657304,76.0084976908,65.0995473377,72.4256888963,45.2941631433,21.7198344413,96.8872856349,74.1625941824,75.2308559138,630.0749517046,63.0074951705,73.2941415394,557.9695106031,23.6213782537,21.7198344413,23.0321526015,40.8709236607,59.1579320794,69.4952322729,73.2941415394,74.589898875,75.4641484469,76.8205018993,81.7503954237,96.8872856349,30.0 11 | 11.5949823521,52.0702126902,74.821283808,28.0926148873,58.5538473912,59.0003032703,45.2576252166,84.6104235854,50.7210042793,4.9959325697,469.7182300501,46.971823005,51.3956084847,588.3993490275,24.2569443465,4.9959325697,10.9350773739,24.7930883802,40.1081221178,48.5356526542,51.3956084847,54.6636665706,58.6877841549,62.1644993778,75.8001977857,84.6104235854,40.0 12 | 66.6387384757,97.2780832555,52.7460367419,2.639933629,69.3645225838,9.5316085033,97.744189715,86.5973051637,40.9085647203,50.2475742716,573.6965570599,57.369655706,59.6923876088,993.3724457071,31.5178115628,2.639933629,8.8424410159,34.6331734769,47.4458714062,51.7466517538,59.6923876088,67.729052119,74.5343573578,88.7334607821,97.3246939015,97.744189715,30.0 13 | 10.9811766073,60.6353249867,97.9075251613,31.7761518992,61.7852193303,24.1817685775,22.9846720584,3.3834649716,65.8958034124,10.7684683055,390.2995753102,39.029957531,27.9789602384,855.9591401012,29.256779387,3.3834649716,10.0299679721,10.9386349469,19.3836234231,23.7029299699,27.9789602384,43.3198211342,60.9802932898,62.6073361468,69.0969755873,97.9075251613,60.0 14 | 85.6468942482,67.3522998113,90.1034559123,68.7842235435,56.4456335735,81.7639108282,6.0499287676,81.1528444756,35.8577362262,60.9730338678,634.1299612541,63.4129961254,68.0682616774,600.6864758352,24.5089060514,6.0499287676,32.8769554803,52.328054104,59.6148137795,64.8005934339,68.0682616774,73.7316719163,81.3361643814,82.5405075122,86.0925504146,90.1034559123,20.0 15 | 73.780692881,32.1058279369,2.6503867935,45.0508597307,69.7998462711,26.0168238543,64.7587227635,99.8539930675,46.0622672457,68.5259593651,528.6053799093,52.8605379909,55.4104950046,709.9559914374,26.6449993702,2.6503867935,23.6801801482,30.8880271204,41.1673501926,45.6577042397,55.4104950046,66.2656174041,68.9081254369,70.596015593,76.3880228996,99.8539930675,50.0 16 | 15.7995850313,43.6257454567,17.9042316042,16.4207117166,82.9019499943,33.0742024351,78.1205853913,72.6792829111,20.7084560301,47.0206602011,428.2554107718,42.8255410772,38.3499739459,639.4286993717,25.2869274403,15.7995850313,16.3585990481,17.6075276267,19.8671887023,28.1279038731,38.3499739459,44.9837113544,54.7182470141,73.7675434072,78.5987218516,82.9019499943,70.0 17 | 76.2363676447,4.6316018328,43.3320402168,81.6002624109,55.6109792553,53.7287788466,19.5864946581,90.2158726472,58.1722882111,1.6484186053,484.7631043289,48.4763104329,54.6698790509,875.8806830407,29.595281432,1.6484186053,4.3332835101,16.5955160931,36.2083765492,49.5700833946,54.6698790509,56.6355028376,63.5915120412,77.309146598,82.4618234346,90.2158726472,40.0 18 | 4.9715126399,56.2129775994,71.5149522293,51.8026781268,47.6116832346,9.5604960807,83.2577025518,12.2074394021,70.4341269098,86.3715245854,493.9450933598,49.394509336,54.0078278631,844.4493686022,29.0594110161,4.9715126399,9.1015977366,11.6780507378,36.9904100848,50.1262801699,54.0078278631,61.9014373235,70.7583745057,73.8635022938,83.5690847551,86.3715245854,40.0 19 | 46.2143829558,25.1346998848,38.9011605643,11.8059081957,21.8991370872,58.7971953675,4.4630019926,9.6745237708,99.7210916597,12.388305692,328.9994071703,32.899940717,23.516918486,774.4104524968,27.8282312139,4.4630019926,9.153371593,11.3796313107,12.2135864431,18.0948045291,23.516918486,30.6412841566,41.0951272817,48.7309454381,62.8895849967,99.7210916597,80.0 20 | 10.2538624313,36.6659626365,44.8343181051,30.384743819,76.3896039221,80.0737172831,98.9670034498,38.4277552832,55.2833453286,47.1853711642,518.465683423,51.8465683423,46.0098446347,630.3256216475,25.1062864966,10.2538624313,28.3716556802,35.409718873,37.8992174892,42.2716929764,46.0098446347,50.42456083,61.6152229067,77.1264265943,81.9630458998,98.9670034498,60.0 21 | 44.5335265249,74.9806525186,99.8274663929,0.2284465823,39.5017110277,5.2575516514,63.6706470046,12.5647049397,74.9960202258,58.112522075,473.6732489429,47.3673248943,51.3230242999,993.5592190017,31.5207744036,0.2284465823,4.7546411445,11.1032742821,31.4206092013,42.520800326,51.3230242999,60.3357720468,67.0636486588,74.98372606,77.4791648425,99.8274663929,50.0 22 | 97.1589684952,50.7842592895,31.0462761205,94.7629996575,81.7359859124,36.7158690933,83.6121386383,69.2147477996,92.2668088693,28.2573887147,665.5554425903,66.555544259,75.475366856,678.8540312397,26.0548274076,28.2573887147,30.7673873799,35.5819504987,46.5637422306,61.8425523955,75.475366856,82.4864470027,86.2085397076,92.766047027,95.0025965413,97.1589684952,30.0 23 | 21.9323491212,16.9918516185,82.0502853021,19.1457145847,82.0251754951,97.1251876093,83.0289103556,66.8969970662,37.8302154131,12.4307444319,519.4574309979,51.9457430998,52.3636062397,1000.1044662432,31.6244283149,12.4307444319,16.5357408999,18.7149419915,21.0963587603,31.4710688964,52.3636062397,72.9482684378,82.0327084372,82.2460103128,84.438538081,97.1251876093,50.0 24 | 23.5217644367,30.2950723097,69.2805457395,98.1327852234,17.7220181096,53.9585073013,80.6326349732,92.696624808,52.1738737356,86.2962823827,604.7101090197,60.471010902,61.6195265204,782.2508730295,27.9687481491,17.7220181096,22.941789804,28.9404107351,45.6102333078,53.244653875,61.6195265204,73.8213814329,82.331729196,87.5763508677,93.2402408496,98.1327852234,30.0 25 | 81.6186810844,65.1736236643,73.0934360065,81.3795325346,45.8039463963,26.9274416845,69.5126025937,98.3123371378,35.4510437232,25.6921324413,602.9647772666,60.2964777267,67.343113129,575.5105108296,23.9898001415,25.6921324413,26.8039107602,33.7463233154,42.6980755944,57.4257527571,67.343113129,70.9449359588,75.5792649649,81.4273622446,83.2880466897,98.3123371378,40.0 26 | 7.670142455,12.0843016542,0.857997546,20.3647618648,70.5528204795,81.2543510459,41.8786649592,54.7222973779,17.6524583716,84.8679895047,391.9057852589,39.1905785259,31.121713412,910.3814045134,30.172527314,0.857997546,6.9889279641,11.2014698144,15.9820113564,19.2798404675,31.121713412,47.0161179267,59.4714543084,72.6931265928,81.6157148918,84.8679895047,60.0 27 | 76.300269831,78.6356462631,29.3073599692,68.7992324121,8.699689107,15.674889693,47.8711935226,71.1499087512,16.516939085,0.1953304745,413.1504591089,41.3150459109,38.5892767459,847.6416454945,29.1142859348,0.1953304745,7.8492532438,14.2798495758,16.2643242674,24.1911916155,38.5892767459,56.2424090784,69.5044353139,72.1799809672,76.5338074742,78.6356462631,60.0 28 | 82.9192868434,24.4546257891,8.8958283886,12.1877973434,40.310045192,90.929857688,58.1188742537,3.9200368803,84.0598778334,94.3674029782,500.1636331901,50.016363319,49.2144597229,1194.2527825735,34.5579626508,3.9200368803,8.3982492378,11.5294035524,20.7745772554,33.9678774308,49.2144597229,68.0390392896,83.2614641404,85.4338738043,91.273612217,94.3674029782,50.0 29 | 32.9425938427,66.1749728024,2.7684078552,28.630843712,98.5904918984,10.3981073014,60.9894967172,50.4718037788,79.6065049712,46.5296733193,477.1028961986,47.7102896199,48.500738549,812.6546999732,28.5070991154,2.7684078552,9.6351373568,24.9842964299,31.6490688035,41.0948415287,48.500738549,54.6788809542,62.5451395428,68.8612792362,81.5049036639,98.5904918984,50.0 30 | 24.2198417895,62.8811448812,43.402511254,66.0069848411,79.3947405647,87.4052930623,20.7611826248,33.1965382677,34.2189243063,17.4610843416,468.9482459333,46.8948245933,38.8107177801,574.2164601114,23.9628141109,17.4610843416,20.4311727965,23.5281099565,30.5035293242,33.8099698909,38.8107177801,51.1939647049,63.8188968692,68.6845359858,80.1957958145,87.4052930623,60.0 31 | 68.4446664061,49.5088236406,94.7993157431,92.1004369855,32.045135973,82.6005493291,67.4332201481,50.1315566245,61.0725810751,46.8706076965,645.0068936218,64.5006893622,64.2529006116,383.8675117207,19.5925371435,32.045135973,45.3880605241,48.9811804518,49.9447367294,56.6961712949,64.2529006116,67.8377986513,72.691431283,84.5005268604,92.3703248613,94.7993157431,30.0 32 | 54.3039214332,86.0079521779,35.6529270299,18.7448701821,45.0332976878,74.634590745,83.5672348272,14.5163948648,77.048605727,55.9170572087,545.4268518835,54.5426851884,55.1104893209,607.5473433442,24.6484754771,14.5163948648,18.3220226504,32.2713156603,42.2191864904,50.595671935,55.1104893209,63.4040706232,75.3587952396,78.3523315471,83.8113065623,86.0079521779,40.0 33 | 97.9809444863,65.7347486354,3.9208303206,97.3952284083,21.6046201531,8.8510819711,60.1347571705,84.8642344121,13.1884281524,57.9120597802,511.5869334899,51.158693349,59.0234084753,1214.1376907377,34.8444786263,3.9208303206,8.358056806,12.3209589161,19.0797625529,43.3890839294,59.0234084753,62.3747537564,71.4735943684,87.3704332113,97.4538000161,97.9809444863,40.0 34 | 27.9891792219,14.1354017425,73.6971973442,28.7963399664,80.0860398915,6.0730826575,70.3002726194,36.6824636236,22.166408645,50.8302697912,410.7566555031,41.0756655503,32.739401795,618.5060409349,24.8697816825,6.0730826575,13.329169834,20.5602072645,26.2423480488,28.4734756686,32.739401795,42.3415860906,56.6712706396,70.9796575643,74.3360815989,80.0860398915,60.0 35 | 4.3447782751,22.6885038894,25.6850461476,88.5708029382,9.4856753945,25.7464301772,20.2521903906,78.5640533082,26.0445660912,31.0224977788,332.4045443907,33.2404544391,25.7157381624,696.490910626,26.3911142362,4.3447782751,8.9715856826,18.0988873914,21.9576098397,24.4864292443,25.7157381624,25.8656845428,27.5379455974,40.5308088847,79.5647282712,88.5708029382,80.0 36 | 95.1204103418,88.7373585254,8.7854308076,56.7356524058,56.1104277615,47.9598258156,60.7928586658,45.5760720186,97.0427731518,97.8891212493,654.7499307431,65.4749930743,58.7642555358,756.9637010415,27.5129733224,8.7854308076,41.8970078975,47.4830750562,53.6652471777,56.485562548,58.7642555358,71.9706586096,90.6522740703,95.5048829038,97.1274079615,97.8891212493,30.0 37 | 22.4616033956,12.1684463229,15.0774442591,6.6057803109,23.3497374691,39.0378260054,8.7419777643,26.4203528874,46.8711846508,64.0007929411,264.7351460066,26.4735146007,22.9056704324,305.1719387489,17.4691710951,6.6057803109,8.528358019,11.4831526112,14.2047448782,19.507939741,22.9056704324,24.5779836364,30.2055948228,40.6044977345,48.5841454798,64.0007929411,90.0 38 | 61.3274615724,30.6471266784,86.2583233044,43.6404513661,65.0664512534,71.846724581,27.9005947057,25.2954373136,40.4151279014,57.0549544413,509.4526531175,50.9452653117,50.3477029037,379.363830954,19.4772644628,25.2954373136,27.6400789665,30.0978202838,37.4847275345,42.3503219802,50.3477029037,58.7639572937,62.4491584767,66.4225059189,73.2878844533,86.2583233044,50.0 39 | 22.6197408512,69.9846635107,32.2401719633,60.5704403017,7.3906242382,14.221628895,22.9169500526,65.1797134429,75.4443452694,93.1115324143,463.6798109394,46.3679810939,46.4053061325,800.988042311,28.3017321433,7.3906242382,13.5385284293,20.94011846,22.8277872922,28.5108831991,46.4053061325,62.4141495582,66.6211984633,71.0765998624,77.2110639839,93.1115324143,50.0 40 | 25.5260163918,15.7576969825,39.6133077331,80.863380013,70.8285118919,14.7999212611,42.276751902,45.3695470002,25.9767866693,91.8537549209,452.8656747658,45.2865674766,40.9450298175,669.2592016873,25.8700444856,14.7999212611,15.6619194103,23.5723525099,25.8415555861,34.1586993076,40.9450298175,43.5138699412,53.0072364677,72.8354855161,81.9624175038,91.8537549209,70.0 41 | 86.059674155,4.944196064,97.1032867208,14.9406766519,7.9526053276,59.4378030393,71.1561471224,21.3652427774,85.6355268043,76.2996692676,524.8948279303,52.489482793,65.2969750809,1180.2376877652,34.3545875796,4.944196064,7.6517644012,13.543062387,19.4378729397,44.2087789346,65.2969750809,73.2135559805,79.1004265286,85.7203562744,87.1640354116,97.1032867208,40.0 42 | 68.541977834,85.0219917018,64.6151974797,87.6245473977,5.768799223,56.2085861806,97.7083769161,84.6915939823,11.6207229905,9.4913919922,571.2931856979,57.1293185698,66.5785876568,1127.9741388357,33.5853262428,5.768799223,9.1191327153,11.1948567908,42.8322272236,61.2525529601,66.5785876568,75.0018242933,84.7907132981,85.542502841,88.6329303496,97.7083769161,30.0 43 | 21.8252871186,17.6007723436,16.1809162237,52.6590979192,41.4591407869,3.7795299198,22.5593924522,55.7091213297,3.2026244327,26.5088661574,261.4847486839,26.1484748684,22.1923397854,304.205998553,17.4415021874,3.2026244327,3.7218393711,13.7006389629,17.1748155076,20.1354812086,22.1923397854,24.1391819343,30.9939485462,43.6991322134,52.9641002603,55.7091213297,80.0 44 | 34.5137145836,72.0012764912,25.4545512609,14.6432414651,8.9594183955,80.9450438246,43.3521937579,20.3208281659,32.1591426153,98.7101865467,431.0595971067,43.1059597107,33.3364285994,835.9132825997,28.9121649587,8.9594183955,14.0748591581,19.1853108257,23.9144343324,29.4773060735,33.3364285994,38.0491062533,51.9469185779,73.7900299579,82.7215580968,98.7101865467,70.0 45 | 22.106062388,36.5907289088,80.3810561541,64.4114118069,62.5987433363,97.0797426533,19.2355337087,91.6151927318,76.5449610539,91.1610315554,641.7244642973,64.1724464297,70.4781864304,753.2367922278,27.4451597231,19.2355337087,21.8190095201,33.6937956046,54.796339008,63.6863444187,70.4781864304,78.079399094,83.6150487745,91.2518637907,92.161647724,97.0797426533,30.0 46 | 43.4580647852,99.6951853856,76.9815567415,29.024757212,19.0946897026,24.4499812834,30.8356213849,54.2888573837,32.8264719341,14.5140532404,425.1692390535,42.5169239054,31.8310466595,666.8201152706,25.8228603232,14.5140532404,18.6366260564,23.3789229672,27.6523244334,30.1112757158,31.8310466595,37.0791090745,46.7073025648,58.8273972552,79.2529196059,99.6951853856,70.0 47 | 37.6929252874,4.9956005067,61.0577545594,97.6813583635,30.590779474,39.2308590002,53.0475239735,69.735837914,50.2283671871,88.1677063648,532.4287126306,53.2428712631,51.6379455803,681.579269329,26.1070731667,4.9956005067,28.0312615773,36.2724961247,38.7694788864,45.8293639123,51.6379455803,56.2516162079,63.6611795658,73.4222116042,89.1190715646,97.6813583635,40.0 48 | 34.6415626351,20.7434788812,35.649718577,64.8204033263,36.519212462,78.4041347448,38.2932690904,94.9739012402,26.3588865753,13.8068777975,444.2114453297,44.421144533,36.0844655195,622.3234458039,24.9464114815,13.8068777975,20.0498187728,25.2358050365,32.1567598172,35.2464562003,36.0844655195,37.2288351133,46.2514093611,67.53714961,80.0611113943,94.9739012402,70.0 49 | 52.1952501033,45.5688938033,76.3985083904,29.7311155591,90.8594347071,74.5198331308,54.8360119108,28.852614155,25.8863295428,71.5408291668,550.3888204694,55.0388820469,53.515631007,466.5050408758,21.5987277606,25.8863295428,28.5559856938,29.5554152783,40.81756033,49.5447075833,53.515631007,61.5179388132,72.434530356,74.8955681827,77.8446010221,90.8594347071,40.0 50 | 86.7163657676,41.9601354282,23.9964707289,8.6837282404,47.420604853,98.106134776,69.8079484515,62.190170493,30.195962172,3.536461154,472.6139820647,47.2613982065,44.6903701406,913.3818303649,30.2222075694,3.536461154,8.1690015318,20.9339222312,28.3361147391,37.2544661257,44.6903701406,53.328431109,64.4755038805,73.1896319147,87.8553426685,98.106134776,60.0 51 | 37.302642921,45.5198649317,52.3702633567,87.0166461449,88.7724385131,98.3747846447,85.0062932353,0.7710717618,59.4031073619,88.0258957855,642.5630086567,64.2563008657,72.2047002986,855.1460481076,29.2428802977,0.7710717618,33.6494858051,43.8764205296,50.3151438292,56.5899697598,72.2047002986,85.8104343992,87.3194210371,88.1752043311,89.7326731263,98.3747846447,30.0 52 | 51.2311564758,42.0472904108,88.8102641329,34.1099769808,86.3833838142,45.5324420705,63.7542359531,17.444162583,84.0406686068,71.5179314837,584.8715125117,58.4871512512,57.4926962145,531.7733148827,23.0602106426,17.444162583,32.443395541,40.4598277248,44.4868965726,48.9516707137,57.4926962145,66.8597141653,75.2747526206,84.5092116483,86.6260718461,88.8102641329,40.0 53 | 1.875006035,13.2264444139,96.8513676431,80.9367355891,3.7156787235,49.4123354089,73.1216032524,54.7864347696,95.609601913,10.5801003985,480.1153081469,48.0115308147,52.0993850892,1311.5168108221,36.2148700235,1.875006035,3.5316114547,9.2072160635,12.4325412093,34.9379790109,52.0993850892,62.1205021627,75.4661429534,83.8713088538,95.733778486,96.8513676431,50.0 54 | 19.7474805638,95.9059906192,91.9850876555,93.3689455967,51.869375119,68.5880307108,59.0326934587,62.4794227071,91.6579273529,94.7857380845,729.4206918683,72.9420691868,80.1229790319,573.0282787223,23.9380090802,19.7474805638,48.6571856635,57.6000297908,61.4454039326,66.1445875093,80.1229790319,91.788791474,92.4002450379,93.6523040943,94.8977633379,95.9059906192,10.0 55 | 63.9007274061,79.5260151383,93.7370509841,38.6166226119,29.5765400864,92.9094638675,29.3599489611,52.6624183636,97.2658494022,47.1316635609,624.686300382,62.4686300382,58.2815728849,648.6587207923,25.4687793346,29.3599489611,29.5548809739,36.8086061068,44.5771512762,50.4501164425,58.2815728849,70.150842499,83.541049757,93.0749812908,94.0899308259,97.2658494022,40.0 56 | 41.8698363472,6.3398147002,53.2657156233,36.8828972336,90.8540935721,84.7513777204,16.4060098119,35.8070371207,8.8731675874,31.3277116045,406.3776613213,40.6377661321,36.3449671771,752.5302680316,27.4322851405,6.3398147002,8.6198322987,14.899441367,26.8512010667,34.0153069142,36.3449671771,38.877672879,45.28860013,59.5628480427,85.3616493056,90.8540935721,70.0 57 | 24.8491826002,40.2121552732,45.6939911004,78.9087822661,19.9041635729,29.2773261201,64.0203290153,89.6702616476,88.0882121623,98.5825004056,579.2069041636,57.9206904164,54.8571600579,787.171067755,28.056569066,19.9041635729,24.3546806974,28.3916974161,36.9317065272,43.5012567695,54.8571600579,69.9757103156,81.6626112349,88.4046220593,90.5614855234,98.5825004056,50.0 58 | 76.0850885883,62.0844989549,54.1744214948,9.5024875365,8.3081006538,34.2477536295,1.9955183845,38.6775039136,52.8085792437,53.7917624693,391.6757148691,39.1675714869,45.7430415787,575.1768686886,23.9828453001,1.9955183845,7.6768424269,9.26361016,26.8241738016,36.9056038,45.7430415787,53.201852534,53.906560177,55.7564369868,63.4845579183,76.0850885883,50.0 59 | 78.1522430945,4.7503012232,38.312696293,21.4868962299,30.2651042119,65.6067256816,52.2390436381,81.6068345215,66.0684417933,12.3017374426,450.7900241297,45.079002413,45.2758699656,686.3907137331,26.1990594055,4.7503012232,11.5465938207,19.6498644724,27.6316418173,35.0936594605,45.2758699656,57.5861164555,65.7452405151,68.4852020536,78.4977022372,81.6068345215,50.0 60 | 55.301294243,48.852774268,68.5775048565,82.124660071,69.1624557599,13.3944986388,21.3387272786,39.989539003,4.1823363863,92.5276771188,495.4514676239,49.5451467624,52.0770342555,794.1170348398,28.1800822362,4.1823363863,12.4732824136,19.7498815507,34.3942954857,45.307480162,52.0770342555,60.6117784884,68.7529901275,71.7548966222,83.1649617758,92.5276771188,50.0 61 | 12.6700594556,45.6893687136,1.2203278486,10.0501604378,13.0465571303,73.4857908916,75.6880897563,89.7251263727,10.1996473502,25.4730952438,357.2482232004,35.72482232,19.259826187,969.0485183784,31.1295441402,1.2203278486,9.1671771789,10.1697499678,11.928935824,12.8959580604,19.259826187,33.5596046317,54.028295367,73.9262506645,77.0917934179,89.7251263727,70.0 62 | 26.3119618408,25.1428648829,76.1302844156,21.6907680966,56.7395692226,21.9403675292,51.7572344281,83.8394377381,89.4307197072,62.106818147,515.090026008,51.5090026008,54.2484018253,632.27506934,25.1450804202,21.6907680966,21.9154075859,24.5023654122,25.9612327535,41.5791253932,54.2484018253,58.8864687923,66.3138580276,77.6721150801,84.398565935,89.4307197072,40.0 63 | 29.2930827476,28.8419682998,46.9614407979,80.9358577244,88.961407356,74.3741279002,5.968201207,7.557732705,22.8136325255,28.7220346741,414.4294859376,41.4429485938,29.0675255237,815.4552692008,28.5561774263,5.968201207,7.3987795552,19.7624525614,26.9495140295,28.7939948495,29.0675255237,36.3604259677,55.1852469286,75.6864738651,81.7384126876,88.961407356,70.0 64 | 31.2369930092,0.1417505089,82.4008044787,10.3215179872,73.7528912257,64.8434082046,23.1622024439,87.1366563253,5.783541454,3.9812626783,382.7610283159,38.2761028316,27.1995977266,1104.4336511634,33.2330204941,0.1417505089,3.5973114613,5.4230856989,8.9601250272,18.0259286612,27.1995977266,44.6795590874,67.516253111,75.4824738763,82.8743896633,87.1366563253,60.0 65 | 13.0818650126,66.905369889,78.5522478633,27.6304526255,85.017492203,88.9921218622,90.5928352382,93.782557454,3.4438626841,81.0001580976,628.9989629295,62.8998962929,79.7762029804,1074.0079147379,32.7720599709,3.4438626841,12.1180647798,24.7207351029,55.1228947099,73.8934966736,79.7762029804,82.6070917398,86.2098811008,89.3122645374,90.9118074598,93.782557454,30.0 66 | 69.6577801835,38.3120888844,11.2781801727,52.3742502555,54.0244544856,89.0069626737,40.0223541074,55.7057954371,47.3043472506,44.1646112129,501.8508246634,50.1850824663,49.8392987531,373.8876623919,19.336174968,11.2781801727,35.6086980132,39.6803010628,42.9219340812,46.0484528355,49.8392987531,53.0343319476,54.5288567711,58.4961923864,71.5926984325,89.0069626737,50.0 67 | 74.6210009791,55.1640396472,42.014782317,42.4467303324,2.1970296744,25.477755256,4.6327869408,63.2501499727,45.2710867859,71.1559656076,426.2313275132,42.6231327513,43.8589085592,579.964733003,24.0824569553,2.1970296744,4.3892112141,21.308761593,37.0536741987,42.2739511263,43.8589085592,49.2282679304,57.5898727449,64.8313130997,71.5024691448,74.6210009791,60.0 68 | 18.3145240415,12.2057086322,41.3450776599,86.720554065,12.3528484721,14.3243668135,49.6331470087,84.3021639157,66.4695910644,54.4175392017,440.0855208747,44.0085520875,45.4891123343,765.4304071639,27.6664129797,12.2057086322,12.3381344881,13.9300631452,17.1174768731,32.1328562126,45.4891123343,51.5469038859,58.0331547605,70.0361056346,84.5440029306,86.720554065,60.0 69 | 95.58178843,43.1188908871,99.1994773503,45.616603503,78.2554319594,39.0455541667,38.6291846167,40.706155682,48.3588656411,67.4552076962,595.9671599325,59.5967159932,46.987734572,508.5300158063,22.5506100983,38.6291846167,39.0039172117,40.3740353789,42.3950703256,44.6175184567,46.987734572,55.9974024631,70.6952749752,81.7207032535,95.943557322,99.1994773503,60.0 70 | 19.6762776934,99.1993462667,43.4134805575,50.3680696711,36.1473562662,28.6170481704,66.7288241442,11.3479143009,24.3957433384,19.2584792618,399.1525396705,39.915253967,32.3822022183,639.0183205755,25.2788116923,11.3479143009,18.4674227657,19.592718007,22.9799036449,26.9285262376,32.3822022183,39.0538059827,45.4998572916,53.6402205657,69.9758763565,99.1993462667,70.0 71 | 77.2611032706,27.363273222,94.5332562551,20.4386191443,11.8721175473,34.6797106788,61.8976492435,13.7913194951,90.7068614848,10.2216848638,442.7655952051,44.2765595205,31.0214919504,1016.5529805967,31.8834279932,10.2216848638,11.707074279,13.4074791055,18.4444292495,24.5934115909,31.0214919504,45.5668861046,66.5066854516,79.9502549134,91.0895009618,94.5332562551,60.0 72 | 95.8575856872,78.4433947876,98.1368092354,85.3535880335,37.7547464799,44.0243833698,17.8116413299,60.2559709921,22.1049366053,17.669698596,557.4127551168,55.7412755117,52.140177181,929.9663570716,30.4953497614,17.669698596,17.7974470565,21.2462775502,33.0598035175,41.5165286139,52.140177181,67.5309405103,80.5164527614,87.4543875642,96.085508042,98.1368092354,50.0 73 | 74.6244412381,12.9844731186,30.0398052204,79.0065750014,63.5066668969,56.5510326065,53.2054602169,24.170280993,29.9128382467,45.0726459268,469.0742194653,46.9074219465,49.1390530718,445.1231038906,21.09794075,12.9844731186,23.0517002055,28.7643267959,30.0017151283,39.0595096443,49.1390530718,54.5436891727,58.6377228936,65.7302217651,75.0626546144,79.0065750014,50.0 74 | 35.9604452737,87.20399593,37.5602785032,75.6010976154,27.6482142974,83.5379122291,21.6914878692,68.8367881812,39.8995004129,90.9037512727,568.8434715848,56.8843471585,54.368144297,647.3194211034,25.4424727789,21.6914878692,27.0525416546,34.2979990784,37.0803285344,38.963811649,54.368144297,71.5425119549,77.9821419995,84.2711289693,87.5739714643,90.9037512727,50.0 75 | 19.3483518437,87.7495876979,7.3211255018,46.156365471,50.0348316506,35.4159424547,35.7451134827,68.1225834414,36.2604333553,29.1036870796,415.2580219787,41.5258021979,36.002773419,485.2451830185,22.0282814359,7.3211255018,18.1456292095,27.1526200324,33.5222658422,35.6134450715,36.002773419,40.2188062016,47.3199053248,53.6523820087,70.0852838671,87.7495876979,70.0 76 | 45.6689749844,58.4629208315,86.3108728081,26.8399612047,99.2281770334,27.9721763451,28.3680504188,81.8236106541,9.4249038491,4.3590662535,468.4587143827,46.8458714383,37.0185127016,996.4515545584,31.5666208923,4.3590662535,8.9183200896,23.3569497336,27.6325118029,28.2097007893,37.0185127016,50.7865533233,65.4711277783,82.7210630849,87.6026032306,99.2281770334,60.0 77 | 62.8265571315,25.9462005459,77.7927775867,63.2135089487,29.4453952461,88.7581324205,57.9322856385,67.9251800757,18.5020637233,64.1851419583,556.5272432752,55.6527243275,63.0200330401,487.2864301096,22.0745652304,18.5020637233,25.2017868636,28.7455563061,49.3862185208,60.8688485343,63.0200330401,63.6021621525,65.3071533935,69.8986995779,78.8893130701,88.7581324205,30.0 78 | 59.6813953947,65.2128662448,32.643487351,39.0921639744,22.0002240036,57.7650001273,56.3575908542,2.0299270749,16.9843638781,56.2038328964,407.9708517995,40.7970851799,47.6479984354,421.2803034288,20.5251139687,2.0299270749,15.4889201978,20.9970519785,29.4505083468,36.5126933251,47.6479984354,56.2653360795,56.7798136361,58.1482791808,60.2345424797,65.2128662448,50.0 79 | 17.8199301008,99.5653437916,94.7338849306,92.4047701526,46.9726786483,69.8104097042,3.556445241,73.1751928572,55.4669229779,32.5749243144,586.0805027187,58.6080502719,62.6386663411,997.9810761084,31.5908384838,3.556445241,16.3935816148,29.6239254717,42.6533523481,52.0692252461,62.6386663411,71.1563229654,78.9440660458,92.8705931082,95.2170308167,99.5653437916,40.0 80 | 86.7532069329,61.1496004742,41.3356478326,28.2334460411,19.5278340951,4.3077885173,1.0016444139,34.6376725473,55.3627727088,82.1213493589,414.4309629221,41.4430962922,37.9866601899,800.5471125453,28.2939412692,1.0016444139,3.977174107,16.4838249795,25.6217624573,32.0759819448,37.9866601899,46.9464977831,57.0988210384,65.3439502511,82.5845351163,86.7532069329,60.0 81 | 13.5193182621,19.1821371671,94.179517217,75.1466028392,88.9545070473,58.4006403107,39.562159311,21.2118500378,7.563751284,23.9678899292,441.6883734055,44.1688373405,31.7650246201,952.8974039165,30.8690363296,7.563751284,12.9237615643,18.0495733861,20.6029361766,22.8654739726,31.7650246201,47.0975517109,63.4244290693,77.9081836808,89.4770080643,94.179517217,60.0 82 | 28.3262274694,78.9052993525,61.3668346778,92.3909092788,14.0129712876,16.0085402429,55.5359878577,93.3483594563,5.878112372,93.4346823487,539.2079243436,53.9207924344,58.4514112677,1127.1262332975,33.572700715,5.878112372,13.199485396,15.6094264518,24.6309213014,44.6520837024,58.4514112677,68.3822205476,82.9509823304,92.5823993143,93.3569917455,93.4346823487,40.0 83 | 56.7069665529,73.9872980863,4.5195152517,59.4928713515,96.6892709024,56.5768137574,86.5092637017,61.1957121175,16.3340373896,26.1665349361,538.1782840472,53.8178284047,58.0999189522,801.6048729876,28.3126274476,4.5195152517,15.1525851758,24.2000354268,47.453730111,56.6549054347,58.0999189522,60.1740076579,65.0331879081,76.4916912094,87.5272644218,96.6892709024,30.0 84 | 80.9528750367,74.9713761266,43.9191470388,49.1046253592,1.438796008,81.8445177749,60.8108829241,48.509781668,3.9008731022,61.9742599782,507.4271350168,50.7427135017,54.9577541417,737.3784522228,27.1547132598,1.438796008,3.6546653928,35.9154922515,47.1325912792,48.8666878827,54.9577541417,61.2762337457,65.8733948227,76.1676759087,81.0420393106,81.8445177749,50.0 85 | 1.3879379723,27.0735116675,24.5108083822,53.1566711608,4.172616126,29.1592625901,79.7265801579,64.6333373617,92.5015445333,73.4596950468,449.7819649987,44.9781964999,41.1579668755,928.5262958199,30.4717294524,1.3879379723,3.8941483106,20.4431699309,26.3047006819,28.3249622211,41.1579668755,57.7473376412,67.2812446672,74.713072069,81.0040765954,92.5015445333,50.0 86 | 37.0952259284,59.4624680933,85.701708775,88.620052347,37.2204889078,64.7573641501,77.0197781269,71.4115807321,14.4379231613,58.174685156,593.9012753777,59.3901275378,62.1099161217,504.1553683605,22.4534043824,14.4379231613,34.8294956516,37.1954363119,51.8884262815,58.9473549183,62.1099161217,67.4190507829,73.0940399505,78.7561642565,85.9935431322,88.620052347,30.0 87 | 41.9338717125,82.5822007377,59.0484443121,27.2040150128,17.8805335425,18.1273884606,67.0179984998,71.5013105422,22.5268427748,8.6466927547,416.4692983497,41.646929835,34.5689433627,629.4768202519,25.0893766414,8.6466927547,16.9571494637,18.0780174769,21.2070064805,25.3331461176,34.5689433627,48.7797007523,61.4393105684,67.9146609083,72.6093995618,82.5822007377,60.0 88 | 24.9651959166,90.0479655247,36.15727867,95.382889593,0.2261363901,0.6743105128,33.1367945764,30.1067052409,3.3952195197,63.4544947185,377.5469906628,37.7546990663,31.6217499087,1092.5935617534,33.0544030615,0.2261363901,0.6294931006,2.8510377184,18.4942029975,28.0501015112,31.6217499087,34.3449882139,44.3464434845,68.7731888797,90.5814579315,95.382889593,70.0 89 | 79.6932297759,4.1134668514,35.0374038797,73.647280084,89.8369476199,89.579350967,60.152402753,81.4335405827,53.5172100179,63.7491894886,630.76002202,63.076002202,68.6982347863,650.6573772844,25.5079865392,4.1134668514,31.9450101769,49.8212487902,58.1618449325,62.3104747944,68.6982347863,76.0656599607,80.2153230179,83.0627026595,89.6051106323,89.8369476199,20.0 90 | 32.6282336377,82.7230034862,25.520239491,18.6653252225,8.121161256,92.3572928645,49.0218959749,11.006033374,78.4030028619,19.2697133403,417.7159015089,41.7715901509,29.0742365643,909.7171059067,30.1615169696,8.121161256,10.7175461622,17.1334668528,19.088396905,23.0200290307,29.0742365643,39.1856985725,57.836228041,79.2670029867,83.686432424,92.3572928645,70.0 91 | 66.0722616594,76.5022270847,72.9312114418,54.8712723423,21.4746861253,25.0498758629,13.2638237439,25.0857676845,16.4976697881,76.3362572994,448.0850530323,44.8085053032,39.9785200134,646.3211637917,25.4228472794,13.2638237439,16.1742851837,20.4792828579,23.9773189416,25.0714109559,39.9785200134,59.3516680691,68.1299465941,73.6122206133,76.3528542779,76.5022270847,50.0 92 | 83.4770285524,98.4195341822,37.1117700823,37.5200630631,99.7001956217,61.1885941587,96.7025047634,78.9983149152,24.6793984435,86.6498338524,704.447237635,70.4447237635,81.2376717338,720.8814217592,26.8492350312,24.6793984435,35.8685329184,37.438404467,54.0880348301,71.8744266126,81.2376717338,84.7461506724,89.6656351257,97.0459106471,98.5476003261,99.7001956217,30.0 93 | 23.7582358532,4.6701700892,91.5487261955,59.4418837223,39.7401862312,13.3102989756,6.1949863564,19.135740865,14.3968681805,68.163622031,340.3607184999,34.03607185,21.4469883591,793.0779274922,28.1616392899,4.6701700892,6.0425047297,11.8872364517,14.070897419,17.2401917912,21.4469883591,30.1510160044,45.6506954785,61.1862313841,70.5021324474,91.5487261955,70.0 94 | 25.9960082825,14.9114078842,16.032426618,56.9942948408,3.1138360966,34.2432999052,27.1417748649,71.8103662133,16.8255093042,86.3350070082,353.403931018,35.3403931018,26.5688915737,672.6632434073,25.9357522237,3.1138360966,13.7316507054,15.8082228713,16.5875844983,22.3278086912,26.5688915737,29.982384881,41.0685983859,59.9575091153,73.2628302928,86.3350070082,70.0 95 | 32.4634619057,13.4045034647,89.4898360595,55.675352551,35.6507610995,82.3420788161,23.3193073887,27.5994650088,64.2086192966,54.2650196236,478.4184052143,47.8418405214,44.9578903615,587.7470090217,24.2434941587,13.4045034647,22.3278269963,26.7434334848,31.0042628367,34.375841422,44.9578903615,54.8291527946,58.2353325747,67.8353112005,83.0568545405,89.4898360595,50.0 96 | 32.1852379013,37.2936587781,94.523374876,54.3622808065,66.8539407197,14.1821998637,60.233220458,39.7367095109,54.8770607915,18.7611518428,473.0088355485,47.3008835549,47.0494951587,518.4000377369,22.7683999819,14.1821998637,18.3032566449,29.5004206896,35.761132515,38.7594892178,47.0494951587,54.5681928005,56.4839086914,61.5573645104,69.6208841354,94.523374876,50.0 97 | 18.6791683082,40.7819013111,21.4156553149,32.9190454911,70.3978272621,76.283344347,94.1690375097,99.0141626447,31.032345118,60.6246410869,545.3171283938,54.5317128394,50.703271199,790.2259888055,28.1109585181,18.6791683082,21.1420066142,29.1090071574,32.3530353792,37.6367589831,50.703271199,64.533915557,72.1634823876,79.8604829796,94.6535500232,99.0141626447,50.0 98 | 18.3432220947,94.5338891353,31.0754375998,84.8799828906,77.8731059283,13.291946426,97.7436863352,78.1369999982,48.559581954,40.8942814451,585.3321338072,58.5332133807,63.2163439412,911.254433094,30.1869911236,13.291946426,17.8380945278,28.5289944988,37.9486282915,45.4934617504,63.2163439412,77.9786635563,80.1598948659,86.8107641395,94.8548688553,97.7436863352,50.0 99 | 10.188567359,39.2516824417,3.0271045398,76.5460240189,9.0262847021,4.7670592088,19.9641600251,37.6376984175,76.7975979485,37.229320826,314.4354994874,31.4435499487,28.5967404256,682.9246377057,26.1328268219,3.0271045398,4.5930637419,8.1744396035,9.8398825619,16.0539229587,28.5967404256,37.3926718626,38.1218936248,46.7105507571,76.5711814119,76.7975979485,80.0 100 | --------------------------------------------------------------------------------