Skip to content

Commit 1438673

Browse files
committed
allow combining histogram with visual(Stairs)
and other plot types such as `Scatter`. Possibly an alternative to MakieOrg#572. The only drawback here is that the `visual(...)` needs to come before `histogram()`, otherwise an error is thrown because `width` is not mapped for other plot types. What do you think of this approach?
1 parent 4a289d6 commit 1438673

File tree

4 files changed

+43
-20
lines changed

4 files changed

+43
-20
lines changed

src/transformations/histogram.jl

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,34 @@ function (h::HistogramAnalysis)(input::ProcessedLayer)
4545
datalimits = h.datalimits === automatic ? defaultdatalimits(input.positional) : h.datalimits
4646
options = valid_options(; datalimits, h.bins, h.closed, h.normalization)
4747

48+
N = length(input.positional)
49+
default_plottype = categoricalplottypes[N]
50+
plottype = Makie.plottype(input.plottype, default_plottype)
51+
4852
output = map(input) do p, n
4953
hist = _histogram(Tuple(p); pairs(n)..., pairs(options)...)
5054
edges, weights = hist.edges, hist.weights
51-
named = length(edges) == 1 ? (; width=diff(first(edges))) : (;)
52-
return (map(midpoints, edges)..., weights), named
55+
named = plottype == BarPlot ? (; width=diff(first(edges))) : (;)
56+
positional = if plottype == Stairs
57+
edges = only(edges)
58+
phantomedge = edges[end] # to bring step back to baseline
59+
edges = vcat(edges, phantomedge)
60+
z = zero(eltype(weights))
61+
heights = vcat(z, weights, z)
62+
(edges, heights)
63+
else
64+
(map(midpoints, edges)..., weights)
65+
end
66+
return positional, named
5367
end
5468

55-
N = length(input.positional)
5669
label = h.normalization == :none ? "count" : string(h.normalization)
5770
labels = set(output.labels, N+1 => label)
58-
attributes = if N == 1
71+
attributes = if plottype == BarPlot
5972
set(output.attributes, :gap => 0, :dodge_gap => 0)
6073
else
6174
output.attributes
6275
end
63-
default_plottype = categoricalplottypes[N]
64-
plottype = Makie.plottype(output.plottype, default_plottype)
6576
return ProcessedLayer(output; plottype, labels, attributes)
6677
end
6778

test/reference_tests.jl

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ reftest("barplot cat color palette") do
2727
draw(scales(Color = (; palette = :Set1_3)))
2828
end
2929

30-
reftest("barplot layout") do
30+
reftest("barplot layout") do
3131
data((; x = ["A", "B", "C"], y = 1:3, z = ["X", "Y", "Z"])) * mapping(:x, :y; layout = :z) * visual(BarPlot) |> draw
3232
end
3333

@@ -244,6 +244,18 @@ reftest("histogram stack") do
244244
draw(specs)
245245
end
246246

247+
reftest("histogram stairs cat color") do
248+
df = (x=[sin.(1:500); sin.(1:500) .* 2], z=repeat(["a", "b"], inner = 500))
249+
specs = data(df) * mapping(:x, layout=:z, color = :z) * visual(Stairs) * histogram()
250+
draw(specs)
251+
end
252+
253+
reftest("histogram scatter cat color") do
254+
df = (x=[sin.(1:500); sin.(1:500) .* 2], z=repeat(["a", "b"], inner = 500))
255+
specs = data(df) * mapping(:x, layout=:z, color = :z) * visual(Scatter) * histogram()
256+
draw(specs)
257+
end
258+
247259
reftest("histogram 2d") do
248260
df = (x=sin.(1:300), y=cos.(1:300))
249261
specs = data(df) * mapping(:x, :y) * histogram()
@@ -736,15 +748,15 @@ function presorted_plot(; with_missing::Bool)
736748
end
737749
group = ["2", "3", "1", "1", "3", "2"]
738750
some_value = sort(exp.(sin.(1:6)))
739-
751+
740752
df = (; countries, group, some_value)
741753

742754
m1 = mapping(:countries, :some_value, color = :group)
743755
m2 = mapping(:countries => presorted, :some_value, color = :group)
744756
m3 = mapping(:countries => presorted, :some_value, color = :group => presorted)
745757

746758
base = data(df) * visual(BarPlot, direction = :x)
747-
759+
748760
f = Figure()
749761
fg1 = draw!(f[1, 1], base * m1)
750762
fg2 = draw!(f[2, 1], base * m2)
@@ -795,7 +807,7 @@ reftest("categorical color from continuous") do
795807
f
796808
end
797809

798-
reftest("title subtitle footnotes") do
810+
reftest("title subtitle footnotes") do
799811
spec = pregrouped(
800812
fill(1:5, 6),
801813
fill(11:15, 6),
@@ -816,7 +828,7 @@ reftest("title subtitle footnotes") do
816828
)
817829
end
818830

819-
reftest("title subtitle footnotes single unconstrained facet") do
831+
reftest("title subtitle footnotes single unconstrained facet") do
820832
spec = data((; x = 1:10, y = 11:20)) * mapping(:x, :y) * visual(Scatter)
821833
draw(
822834
spec;
@@ -831,7 +843,7 @@ reftest("title subtitle footnotes single unconstrained facet") do
831843
)
832844
end
833845

834-
reftest("title") do
846+
reftest("title") do
835847
spec = pregrouped(
836848
fill(1:5, 6),
837849
fill(11:15, 6),
@@ -847,7 +859,7 @@ reftest("title") do
847859
)
848860
end
849861

850-
reftest("title subtitle footnotes settings") do
862+
reftest("title subtitle footnotes settings") do
851863
spec = pregrouped(
852864
fill(1:5, 6),
853865
fill(11:15, 6),
@@ -877,10 +889,10 @@ reftest("title subtitle footnotes settings") do
877889
),
878890
axis = (; width = 100, height = 100)
879891
)
880-
892+
881893
end
882894

883-
reftest("title subtitle footnotes fontsize inherit") do
895+
reftest("title subtitle footnotes fontsize inherit") do
884896
spec = pregrouped(
885897
fill(1:5, 6),
886898
fill(11:15, 6),
@@ -902,7 +914,7 @@ reftest("title subtitle footnotes fontsize inherit") do
902914
)
903915
end
904916

905-
reftest("dodge barplot with errorbars") do
917+
reftest("dodge barplot with errorbars") do
906918
f = Figure()
907919
df = (
908920
x = [1, 1, 2, 2],
@@ -960,7 +972,7 @@ reftest("dodge scatter with rangebars") do
960972
yhigh = cos.(range(0, 2pi, length = 20)) .+ 0.3,
961973
dodge = repeat(["A", "B"], 10)
962974
)
963-
975+
964976
f = Figure()
965977
spec1 = data(df) * (mapping(:x, :y, dodge_x = :dodge, color = :dodge) * visual(Scatter) + mapping(:x, :ylow, :yhigh, dodge_x = :dodge, color = :dodge) * visual(Rangebars))
966978
spec2 = data(df) * (mapping(:y, :x, dodge_y = :dodge, color = :dodge) * visual(Scatter) + mapping(:x, :ylow, :yhigh, dodge_y = :dodge, color = :dodge) * visual(Rangebars, direction = :x))
@@ -974,10 +986,10 @@ end
974986
reftest("manual legend labels in visual") do
975987
df_subjects = (; x = repeat(1:10, 10), y = cos.(1:100), id = repeat(1:10, inner = 10))
976988
df_func = (; x = range(1, 10, length = 20), y = cos.(range(1, 10, length = 20)))
977-
989+
978990
spec1 = data(df_subjects) * mapping(:x, :y, group = :id => nonnumeric) * visual(Lines, linestyle = :dash, color = (:black, 0.2), label = "Subject data")
979991
spec2 = data(df_func) * mapping(:x, :y) * (visual(Lines, color = :tomato) + visual(Scatter, markersize = 12, color = :tomato, strokewidth = 2)) * visual(label = L"\cos(x)")
980-
992+
981993
draw(spec1 + spec2)
982994
end
983995

@@ -986,7 +998,7 @@ reftest("manual legend order") do
986998
spec1 = data(df) * mapping(:x, :y, color = :group) * visual(Lines)
987999

9881000
spec2 = data((; x = 1:10, y = cos.(1:10) .+ 2)) * mapping(:x, :y) * visual(Scatter, color = :purple, label = "Scatter")
989-
1001+
9901002
f = Figure()
9911003
fg = draw!(f[1, 1], spec1 + spec2)
9921004
legend!(f[1, 2], fg)
10.3 KB
Loading
9.94 KB
Loading

0 commit comments

Comments
 (0)