Class: Statsample::Histogram

Inherits:
Object
  • Object
show all
Includes:
Enumerable, GetText
Defined in:
lib/statsample/histogram.rb

Overview

A histogram consists of a set of bins which count the number of events falling into a given range of a continuous variable x.

This implementations follows convention of GSL for specification.

* Verbatim: *

The range for bin[i] is given by range[i] to range[i+1]. 
For n bins there are n+1 entries in the array range. 
Each bin is inclusive at the lower end and exclusive at the upper end. 
Mathematically this means that the bins are defined 
by the following inequality,

 bin[i] corresponds to range[i] <= x < range[i+1]

Here is a diagram of the correspondence between ranges and bins
on the number-line for x,

    [ bin[0] )[ bin[1] )[ bin[2] )[ bin[3] )[ bin[4] )
 ---|---------|---------|---------|---------|---------|---  x
  r[0]      r[1]      r[2]      r[3]      r[4]      r[5]

In this picture the values of the range array are denoted by r. 
On the left-hand side of each bin the square bracket ‘[’ denotes 
an inclusive lower bound ( r <= x), and the round parentheses ‘)’ 
on the right-hand side denote an exclusive upper bound (x < r). 
Thus any samples which fall on the upper end of the histogram are 
excluded. 
If you want to include this value for the last bin you will need to 
add an extra bin to your histogram.

Reference:

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(p1, min_max = false, opts = Hash.new) ⇒ Histogram

Returns a new instance of Histogram.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/statsample/histogram.rb', line 71

def initialize(p1, min_max=false, opts=Hash.new)
  
  if p1.is_a? Array
    range=p1
    @n_bins=p1.size-1
  elsif p1.is_a? Integer
    @n_bins=p1
  end
  
  @bin=[0.0]*(@n_bins)
  if(min_max)
    min, max=min_max[0], min_max[1]
    range=Array.new(@n_bins+1)
    (@n_bins+1).times {|i| range[i]=min+(i*(max-min).quo(@n_bins)) }
  end
  range||=[0.0]*(@n_bins+1)
  set_ranges(range)
  @name=""
  opts.each{|k,v|
  self.send("#{k}=",v) if self.respond_to? k
  }
end

Instance Attribute Details

#binObject (readonly)

Returns the value of attribute bin.



65
66
67
# File 'lib/statsample/histogram.rb', line 65

def bin
  @bin
end

#nameObject

Returns the value of attribute name.



64
65
66
# File 'lib/statsample/histogram.rb', line 64

def name
  @name
end

#rangeObject (readonly)

Returns the value of attribute range.



66
67
68
# File 'lib/statsample/histogram.rb', line 66

def range
  @range
end

Class Method Details

.alloc(n_bins, range = nil, opts = Hash.new) ⇒ Object

Alloc n_bins, using range as ranges of bins



45
46
47
48
# File 'lib/statsample/histogram.rb', line 45

def alloc(n_bins, range=nil, opts=Hash.new)
  Histogram.new(n_bins, range, opts)
  
end

.alloc_uniform(n_bins, p1 = nil, p2 = nil) ⇒ Object

Alloc n_bins bins, using p1 as minimum and p2 as maximum



51
52
53
54
55
56
57
58
59
60
61
# File 'lib/statsample/histogram.rb', line 51

def alloc_uniform(n_bins, p1=nil,p2=nil)
  if p1.is_a? Array
    min,max=p1
  else
    min,max=p1,p2
  end
  range=max - min
  step=range / n_bins.to_f
  range=(n_bins+1).times.map {|i| min + (step*i)}
  Histogram.new(range)
end

Instance Method Details

#binsObject

Number of bins



95
96
97
# File 'lib/statsample/histogram.rb', line 95

def bins
  @n_bins
end

#eachObject



134
135
136
137
138
139
140
# File 'lib/statsample/histogram.rb', line 134

def each
  bins.times.each do |i|
    r=get_range(i)
    arg={:i=>i, :low=>r[0],:high=>r[1], :middle=>(r[0]+r[1]) / 2.0,  :value=>@bin[i]}
    yield arg
  end
end

#estimated_meanObject Also known as: mean



153
154
155
156
157
158
159
160
# File 'lib/statsample/histogram.rb', line 153

def estimated_mean
  sum,n=0,0
  each do |v|
    sum+= v[:value]* v[:middle]
    n+=v[:value]
  end
  sum / n
end

#estimated_standard_deviationObject Also known as: sigma



150
151
152
# File 'lib/statsample/histogram.rb', line 150

def estimated_standard_deviation
  Math::sqrt(estimated_variance)
end

#estimated_varianceObject



141
142
143
144
145
146
147
148
149
# File 'lib/statsample/histogram.rb', line 141

def estimated_variance
  sum,n=0,0
  mean=estimated_mean
  each do |v|
    sum+=v[:value]*(v[:middle]-mean)**2
    n+=v[:value]
  end
  sum / (n-1)
end

#get_range(i) ⇒ Object



117
118
119
# File 'lib/statsample/histogram.rb', line 117

def get_range(i)
  [@range[i],@range[i+1]]
end

#increment(x, w = 1) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/statsample/histogram.rb', line 99

def increment(x, w=1)
  if x.respond_to? :each
    x.each{|y| increment(y,w) }
  elsif x.is_a? Numeric
    (range.size - 1).times do |i|
      if x >= range[i] and x < range[i+1]
        @bin[i] += w
        break
      end
    end
  end
end

#maxObject



121
122
123
# File 'lib/statsample/histogram.rb', line 121

def max
  @range.last
end

#max_valObject



128
129
130
# File 'lib/statsample/histogram.rb', line 128

def max_val
  @bin.max
end

#minObject



125
126
127
# File 'lib/statsample/histogram.rb', line 125

def min
  @range.first
end

#min_valObject



131
132
133
# File 'lib/statsample/histogram.rb', line 131

def min_val
  @bin.min
end

#report_building(generator) ⇒ Object



169
170
171
172
# File 'lib/statsample/histogram.rb', line 169

def report_building(generator)
  hg=Statsample::Graph::Histogram.new(self)
  generator.parse_element(hg)
end

#report_building_text(generator) ⇒ Object



173
174
175
176
177
178
# File 'lib/statsample/histogram.rb', line 173

def report_building_text(generator)
  @range.each_with_index do |r,i|
    next if i==@bin.size
    generator.text(sprintf("%5.2f : %d", r, @bin[i]))
  end
end

#set_ranges(range) ⇒ Object



112
113
114
115
# File 'lib/statsample/histogram.rb', line 112

def set_ranges(range)
  raise "Range size should be bin+1" if range.size!=@bin.size+1
  @range=range
end

#sum(start = nil, _end = nil) ⇒ Object



164
165
166
167
168
# File 'lib/statsample/histogram.rb', line 164

def sum(start=nil,_end=nil)
  start||=0
  _end||=@n_bins-1
  (start.._end).inject(0) {|ac,i| ac+@bin[i]}
end