Skip to content

Commit 0e5ec86

Browse files
committed
Pass integer barplot values as integers
1 parent 8dfbbe8 commit 0e5ec86

3 files changed

Lines changed: 59 additions & 4 deletions

File tree

shard.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ version: 2.0
22
shards:
33
unicode_plot:
44
git: https://github.com/crystal-data/unicode_plot.cr.git
5-
version: 0.1.0+git.commit.fc5d4b3c8b452e2c4e540ecfaebd5d11217b8c21
5+
version: 0.1.0+git.commit.312f8c81ee4cc829957660ee4ca721ef0907bd75
66

spec/barplot_spec.cr

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
require "./spec_helper"
2+
3+
describe "barplot value labels" do
4+
it "formats all-integer bar values as integers" do
5+
output = render_barplot("a\t3\nb\t7\nc\t12\n")
6+
7+
output.should contain(" 3 ")
8+
output.should contain(" 7 ")
9+
output.should contain(" 12 ")
10+
output.should_not contain("3.0")
11+
output.should_not contain("7.0")
12+
output.should_not contain("12.0")
13+
end
14+
15+
it "treats explicit float bar values as floats" do
16+
output = render_barplot("a\t3.0\nb\t7.0\nc\t12.0\n")
17+
18+
output.should contain(" 3.0 ")
19+
output.should contain(" 7.0 ")
20+
output.should contain(" 12.0 ")
21+
end
22+
23+
it "treats mixed integer and float bar values as floats" do
24+
output = render_barplot("a\t3\nb\t3.0\nc\t12\n")
25+
26+
output.should contain(" 3.0 ")
27+
output.should contain(" 12.0 ")
28+
end
29+
end
30+
31+
private def render_barplot(input : String) : String
32+
data = YouPlot2::DSV.parse(input, '\t', nil, false)
33+
plot = YouPlot2::Backends::UnicodePlot.barplot(data, YouPlot2::Parameters.new)
34+
io = IO::Memory.new
35+
::UnicodePlot.show_plot(io, plot, use_color: false)
36+
io.to_s
37+
end

src/youplot2/backends/unicode_plot.cr

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,26 +203,40 @@ module YouPlot2
203203
# -----------------------------------------------------------------------
204204
# String → Symbol helpers (runtime conversion via case/when)
205205
# -----------------------------------------------------------------------
206+
private alias BarValues = Array(Float64) | Array(Int64)
207+
206208
private def prepare_bar_data(series : Array(Array(String?)),
207209
headers : Array(String)?,
208210
fmt : String?,
209-
params : Parameters) : {Array(String), Array(Float64)}
211+
params : Parameters) : {Array(String), BarValues}
210212
validate_yx_format(fmt, "barplot")
211213
if series.size == 1
212214
params.title ||= headers[0] if headers
213215
labels = (1..series[0].size).map(&.to_s)
214-
values = series[0].map { |v| to_f64_or_zero(v) }
216+
values = parse_bar_values(series[0])
215217
else
216218
require_series_count(series, 2, "barplot")
217219
x_col, y_col = fmt == "yx" ? {1, 0} : {0, 1}
218220
params.title ||= headers[y_col] if headers
219221
labels = series[x_col].map { |v| v || "" }
220-
values = series[y_col].map { |v| to_f64_or_zero(v) }
222+
values = parse_bar_values(series[y_col])
221223
end
222224
require_values(values, "barplot")
223225
{labels, values}
224226
end
225227

228+
private def parse_bar_values(raw_values : Array(String?)) : BarValues
229+
if raw_values.all? { |v| integer_literal?(v) }
230+
raw_values.map { |v| v.to_s.to_i64 }
231+
else
232+
raw_values.map { |v| to_f64_or_zero(v) }
233+
end
234+
end
235+
236+
private def integer_literal?(value : String?) : Bool
237+
value.to_s.strip.matches?(/\A[+-]?\d+\z/)
238+
end
239+
226240
private def line_single(data : Data, params : Parameters) : ::UnicodePlot::Plot
227241
headers = data.headers
228242
require_series(data, 1, "lineplot")
@@ -502,6 +516,10 @@ module YouPlot2
502516
raise DataError.new("#{label} has no data values") if values.empty?
503517
end
504518

519+
private def require_values(values : Array(Int64), label : String) : Nil
520+
raise DataError.new("#{label} has no data values") if values.empty?
521+
end
522+
505523
private def require_xy_values(x : Array(Float64), y : Array(Float64), label : String) : Nil
506524
require_values(x, label)
507525
require_values(y, label)

0 commit comments

Comments
 (0)