@@ -4,18 +4,6 @@ module UnicodePlot
44 (Math .log2(n) + 1 ).ceil.to_i32
55 end
66
7- # Scott's rule: bin_width = 3.49 * σ * n^(-1/3).
8- private def scott_bins (data : Array (Float64 )) : Int32
9- n = data.size
10- return 2 if n < 2
11- mean = data.sum / n
12- std = Math .sqrt(data.sum { |v | (v - mean) ** 2 } / n)
13- return sturges(n) if std == 0.0
14- bw = 3.49 * std * (n.to_f ** (-1.0 / 3.0 ))
15- bins = ((data.max - data.min) / bw).ceil.to_i32
16- Math .max(sturges(n), Math .max(2 , bins))
17- end
18-
197 # Round step up to next "nice" value ({1,2,2.5,5} × 10^k), matching Julia's histrange.
208 private def nice_hist_step (step : Float64 ) : Float64
219 return step if step <= 0.0
@@ -45,7 +33,7 @@ module UnicodePlot
4533 color : Symbol | UInt32 | {Int32 , Int32 , Int32 } = :green ,
4634 title : String = " " ,
4735 xlabel : String = " " ,
48- ylabel : String = " " ,
36+ ylabel : String = " " , # currently unused; kept for API compatibility
4937 border : Symbol = :barplot ,
5038 margin : Int32 = 3 ,
5139 padding : Int32 = 1 ,
@@ -56,41 +44,40 @@ module UnicodePlot
5644 symbols : Array (Char ) = ['▏' , '▎' , '▍' , '▌' , '▋' , '▊' , '▉' , '█' ],
5745 width : Int32 ? = nil ,
5846 ) : Plot
47+ if vertical
48+ unless xscale.is_a?(Symbol ) && xscale == :identity
49+ raise ArgumentError .new(" xscale is not supported for vertical histogram" )
50+ end
51+ end
52+
5953 return barplot([] of String , [] of Float64 ) if data.empty?
6054
61- scale_fn = xscale.is_a?(Symbol ) ? scale_callback(xscale.as(Symbol )) : xscale.as(Proc (Float64 , Float64 ))
62- scaled_data = data.map { |v | scale_fn.call(v) }.select(& .finite?)
63- return barplot([] of String , [] of Float64 ) if scaled_data.empty?
55+ raw_data = data.select(& .finite?)
56+ return barplot([] of String , [] of Float64 ) if raw_data.empty?
6457
65- n_bins = histogram_bin_count(scaled_data, nbins, vertical)
66- dmin, dmax = histogram_data_bounds(scaled_data)
67- xlab = xscale.is_a?(Symbol ) ? transform_name(xscale.as(Symbol ), xlabel) : transform_name(scale_fn, xlabel)
58+ n_bins = histogram_bin_count(raw_data, nbins)
59+ dmin, dmax = histogram_data_bounds(raw_data)
6860
6961 if vertical
70- histogram_vertical_plot(scaled_data , n_bins, dmin, dmax,
71- stats: stats, xlabel: xlab ,
62+ histogram_vertical_plot(raw_data , n_bins, dmin, dmax,
63+ stats: stats, xlabel: xlabel ,
7264 color: color, title: title,
7365 unicode_exponent: unicode_exponent,
7466 thousands_separator: thousands_separator,
7567 width: width)
7668 else
77- histogram_horizontal_plot(scaled_data , n_bins, dmin, dmax,
69+ histogram_horizontal_plot(raw_data , n_bins, dmin, dmax,
7870 closed: closed,
79- color: color, title: title, xlabel: xlab,
71+ xscale: xscale,
72+ color: color, title: title, xlabel: xlabel,
8073 border: border, margin: margin, padding: padding,
8174 labels: labels, unicode_exponent: unicode_exponent,
8275 thousands_separator: thousands_separator, symbols: symbols, width: width)
8376 end
8477 end
8578
86- private def histogram_bin_count (data : Array (Float64 ), nbins : Int32 ?, vertical : Bool ) : Int32
87- n_bins = if nbins
88- nbins
89- elsif vertical
90- scott_bins(data)
91- else
92- Math .min(scott_bins(data), Math .max(sturges(data.size), 30 ))
93- end
79+ private def histogram_bin_count (data : Array (Float64 ), nbins : Int32 ?) : Int32
80+ n_bins = nbins || sturges(data.size)
9481 Math .max(n_bins, 2 )
9582 end
9683
@@ -154,6 +141,7 @@ module UnicodePlot
154141 dmax : Float64 ,
155142 * ,
156143 closed : Symbol ,
144+ xscale : Symbol | Proc (Float64 , Float64 ),
157145 color : Symbol | UInt32 | {Int32 , Int32 , Int32 },
158146 title : String ,
159147 xlabel : String ,
@@ -186,6 +174,7 @@ module UnicodePlot
186174
187175 histogram_horizontal(counts, edge_min, bin_width, n_actual,
188176 closed: closed,
177+ xscale: xscale,
189178 color: color, title: title, xlabel: xlabel,
190179 border: border, margin: margin, padding: padding,
191180 labels: labels, unicode_exponent: unicode_exponent,
@@ -274,7 +263,7 @@ module UnicodePlot
274263
275264 private def histogram_horizontal (
276265 counts : Array (Float64 ), dmin : Float64 , bin_width : Float64 , n_bins : Int32 ,
277- * , closed : Symbol , color : Symbol | UInt32 | {Int32 , Int32 , Int32 }, title : String , xlabel : String ,
266+ * , closed : Symbol , xscale : Symbol | Proc ( Float64 , Float64 ), color : Symbol | UInt32 | {Int32 , Int32 , Int32 }, title : String , xlabel : String ,
278267 border : Symbol , margin : Int32 , padding : Int32 , labels : Bool ,
279268 unicode_exponent : Bool , thousands_separator : Char ,
280269 symbols : Array (Char ), width : Int32 ?,
@@ -308,6 +297,7 @@ module UnicodePlot
308297 labels_arr, counts,
309298 color: color, title: title,
310299 xlabel: xlabel.empty? ? " Frequency" : xlabel,
300+ xscale: xscale,
311301 border: border, margin: margin, padding: padding,
312302 labels: labels, unicode_exponent: unicode_exponent,
313303 thousands_separator: thousands_separator, symbols: symbols,
0 commit comments