Class: Statsample::Graph::Boxplot
- Includes:
- Summarizable
- Defined in:
- lib/statsample/graph/boxplot.rb
Overview
Boxplot
From Wikipedia: In descriptive statistics, a box plot or boxplot (also known as a box-and-whisker diagram or plot) is a convenient way of graphically depicting groups of numerical data through their five-number summaries: the smallest observation (sample minimum), lower quartile (Q1), median (Q2), upper quartile (Q3), and largest observation (sample maximum). A boxplot may also indicate which observations, if any, might be considered outliers.
Usage
Svg output
a = Daru::Vector.new([1,2,3,4])
b = Daru::Vector.new([3,4,5,6])
puts Statsample::Graph::Boxplot.new(:vectors=>).to_svg
Using ReportBuilder
a = Daru::Vector.new([1,2,3,4])
b = Daru::Vector.new([3,4,5,6])
rb=ReportBuilder.new
rb.add(Statsample::Graph::Boxplot.new(:vectors=>[a,b]))
rb.save_html('boxplot.html')
Instance Attribute Summary collapse
-
#groups ⇒ Object
Array with assignation to groups of bars For example, for four vectors, boxplot.groups= Assign same color to first and third element, and different to second and fourth.
-
#height ⇒ Object
Total height of Boxplot.
-
#label_angle ⇒ Object
The rotation angle, in radians.
-
#margin_bottom ⇒ Object
Bottom margin.
-
#margin_left ⇒ Object
Left margin.
-
#margin_right ⇒ Object
Right margin.
-
#margin_top ⇒ Object
Top margin.
-
#maximum ⇒ Object
Maximum value on y-axis.
-
#minimum ⇒ Object
Minimum value on y-axis.
-
#name ⇒ Object
Returns the value of attribute name.
-
#vectors ⇒ Object
Vectors to box-ploting.
-
#width ⇒ Object
Total width of Boxplot.
-
#x_scale ⇒ Object
readonly
Returns the value of attribute x_scale.
-
#y_scale ⇒ Object
readonly
Returns the value of attribute y_scale.
Instance Method Summary collapse
-
#initialize(opts = Hash.new) ⇒ Boxplot
constructor
Create a new Boxplot.
-
#report_building(builder) ⇒ Object
:nodoc:.
-
#rubyvis_panel ⇒ Object
Returns a Rubyvis panel with scatterplot.
-
#to_svg ⇒ Object
Returns SVG with scatterplot.
Methods included from Summarizable
Constructor Details
#initialize(opts = Hash.new) ⇒ Boxplot
Create a new Boxplot. Parameters: Hash of options
-
:vectors: Array of vectors
-
:groups: Array of same size as :vectors:, with name of groups
to colorize vectors
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/statsample/graph/boxplot.rb', line 58 def initialize(opts=Hash.new) @vectors=opts.delete :vectors raise "You should define vectors" if @vectors.nil? opts_default={ :name=>_("Boxplot"), :groups=>nil, :width=>400, :height=>300, :margin_top=>10, :margin_bottom=>20, :margin_left=>20, :margin_right=>20, :minimum=>nil, :maximum=>nil, :label_angle=>0 } @opts=opts_default.merge(opts) opts_default.keys.each {|k| send("#{k}=", @opts[k]) } end |
Instance Attribute Details
#groups ⇒ Object
Array with assignation to groups of bars For example, for four vectors,
boxplot.groups=[1,2,1,3]
Assign same color to first and third element, and different to second and fourth
41 42 43 |
# File 'lib/statsample/graph/boxplot.rb', line 41 def groups @groups end |
#height ⇒ Object
Total height of Boxplot
27 28 29 |
# File 'lib/statsample/graph/boxplot.rb', line 27 def height @height end |
#label_angle ⇒ Object
The rotation angle, in radians. Text is rotated clockwise relative to the anchor location. For example, with the default left alignment, an angle of Math.PI / 2 causes text to proceed downwards. The default angle is zero.
51 52 53 |
# File 'lib/statsample/graph/boxplot.rb', line 51 def label_angle @label_angle end |
#margin_bottom ⇒ Object
Bottom margin
31 32 33 |
# File 'lib/statsample/graph/boxplot.rb', line 31 def margin_bottom @margin_bottom end |
#margin_left ⇒ Object
Left margin
33 34 35 |
# File 'lib/statsample/graph/boxplot.rb', line 33 def margin_left @margin_left end |
#margin_right ⇒ Object
Right margin
35 36 37 |
# File 'lib/statsample/graph/boxplot.rb', line 35 def margin_right @margin_right end |
#margin_top ⇒ Object
Top margin
29 30 31 |
# File 'lib/statsample/graph/boxplot.rb', line 29 def margin_top @margin_top end |
#maximum ⇒ Object
Maximum value on y-axis. Automaticly defined from data
45 46 47 |
# File 'lib/statsample/graph/boxplot.rb', line 45 def maximum @maximum end |
#minimum ⇒ Object
Minimum value on y-axis. Automaticly defined from data
43 44 45 |
# File 'lib/statsample/graph/boxplot.rb', line 43 def minimum @minimum end |
#name ⇒ Object
Returns the value of attribute name.
23 24 25 |
# File 'lib/statsample/graph/boxplot.rb', line 23 def name @name end |
#vectors ⇒ Object
Vectors to box-ploting
47 48 49 |
# File 'lib/statsample/graph/boxplot.rb', line 47 def vectors @vectors end |
#width ⇒ Object
Total width of Boxplot
25 26 27 |
# File 'lib/statsample/graph/boxplot.rb', line 25 def width @width end |
#x_scale ⇒ Object (readonly)
Returns the value of attribute x_scale.
52 53 54 |
# File 'lib/statsample/graph/boxplot.rb', line 52 def x_scale @x_scale end |
#y_scale ⇒ Object (readonly)
Returns the value of attribute y_scale.
52 53 54 |
# File 'lib/statsample/graph/boxplot.rb', line 52 def y_scale @y_scale end |
Instance Method Details
#report_building(builder) ⇒ Object
:nodoc:
229 230 231 232 233 |
# File 'lib/statsample/graph/boxplot.rb', line 229 def report_building(builder) # :nodoc: builder.section(:name=>name) do |b| b.image(to_svg, :type=>'svg', :width=>width, :height=>height) end end |
#rubyvis_panel ⇒ Object
Returns a Rubyvis panel with scatterplot
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/statsample/graph/boxplot.rb', line 80 def rubyvis_panel # :nodoc: that=self min,max=@minimum, @maximum min||=@vectors.map {|v| v.min}.min max||=@vectors.map {|v| v.max}.max margin_hor=margin_left + margin_right margin_vert=margin_top + margin_bottom x_scale = pv.Scale.ordinal(@vectors.size.times.map.to_a).split_banded(0, width-margin_hor, 4.0/5) y_scale=Rubyvis::Scale.linear(min,max).range(0,height-margin_vert) y_scale.nice # cache data colors=Rubyvis::Colors.category10 data=@vectors.map {|v| out={:percentil_25=>v.percentil(25), :median=>v.median, :percentil_75=>v.percentil(75), :name=>v.name} out[:iqr]=out[:percentil_75] - out[:percentil_25] irq_max=out[:percentil_75] + out[:iqr] irq_min=out[:percentil_25] - out[:iqr] # Find the last data inside the margin min = out[:percentil_25] max = out[:percentil_75] v.each {|d| min=d if d < min and d > irq_min max=d if d > max and d < irq_max } # Whiskers! out[:low_whisker]=min out[:high_whisker]=max # And now, data outside whiskers out[:outliers]=v.to_a.find_all {|d| d < min or d > max } out } vis=Rubyvis::Panel.new do |pan| pan.width width - margin_hor pan.height height - margin_vert pan.bottom margin_bottom pan.left margin_left pan.right margin_right pan.top margin_top # Y axis pan.rule do data y_scale.ticks bottom y_scale stroke_style {|d| d!=0 ? "#eee" : "#000"} label(:anchor=>'left') do text y_scale.tick_format end end pan.rule do bottom 0 stroke_style 'black' end # Labels pan.label do |l| l.data data l.text_angle that.label_angle l.left {|v| x_scale[index] } l.bottom(-15) l.text {|v,x| v[:name]} end pan.panel do |bp| bp.data data bp.left {|v| x_scale[index]} bp.width x_scale.range_band # Bar bp. do |b| b.bottom {|v| y_scale[v[:percentil_25]]} b.height {|v| y_scale[v[:percentil_75]] - y_scale[v[:percentil_25]] } b.line_width 1 b.stroke_style {|v| if that.groups colors.scale(that.groups[parent.index]).darker else colors.scale(index).darker end } b.fill_style {|v| if that.groups colors.scale(that.groups[parent.index]) else colors.scale(index) end } end # Median bp.rule do |r| r.bottom {|v| y_scale[v[:median]]} r.width x_scale.range_band r.line_width 2 end ## # Whiskeys ## # Low whiskey bp.rule do |r| r.visible {|v| v[:percentil_25] > v[:low_whisker]} r.bottom {|v| y_scale[v[:low_whisker]]} end bp.rule do |r| r.visible {|v| v[:percentil_25] > v[:low_whisker]} r.bottom {|v| y_scale[v[:low_whisker]]} r.left {|v| x_scale.range_band / 2.0} r.height {|v| y_scale.scale(v[:percentil_25]) - y_scale.scale(v[:low_whisker])} end # High whiskey bp.rule do |r| r.visible {|v| v[:percentil_75] < v[:high_whisker]} r.bottom {|v| y_scale.scale(v[:high_whisker])} end bp.rule do |r| r.visible {|v| v[:percentil_75] < v[:high_whisker]} r.bottom {|v| y_scale.scale(v[:percentil_75])} r.left {|v| x_scale.range_band / 2.0} r.height {|v| y_scale.scale(v[:high_whisker]) - y_scale.scale(v[:percentil_75])} end # Outliers bp.dot do |dot| dot.shape_size 4 dot.data {|v| v[:outliers]} dot.left {|v| x_scale.range_band / 2.0} dot.bottom {|v| y_scale.scale(v)} dot.title {|v| v} end end end vis end |
#to_svg ⇒ Object
Returns SVG with scatterplot
224 225 226 227 228 |
# File 'lib/statsample/graph/boxplot.rb', line 224 def to_svg rp=rubyvis_panel rp.render rp.to_svg end |