Skip to content

Commit

Permalink
allow combining histogram with visual(Stairs)
Browse files Browse the repository at this point in the history
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?
  • Loading branch information
simeonschaub committed Jan 30, 2025
1 parent 416ab6e commit 60cb12c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 20 deletions.
23 changes: 17 additions & 6 deletions src/transformations/histogram.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,34 @@ function (h::HistogramAnalysis)(input::ProcessedLayer)
datalimits = h.datalimits === automatic ? defaultdatalimits(input.positional) : h.datalimits
options = valid_options(; datalimits, h.bins, h.closed, h.normalization)

N = length(input.positional)
default_plottype = categoricalplottypes[N]
plottype = Makie.plottype(input.plottype, default_plottype)

output = map(input) do p, n
hist = _histogram(Tuple(p); pairs(n)..., pairs(options)...)
edges, weights = hist.edges, hist.weights
named = length(edges) == 1 ? (; width=diff(first(edges))) : (;)
return (map(midpoints, edges)..., weights), named
named = plottype == BarPlot ? (; width=diff(first(edges))) : (;)
positional = if plottype == Stairs
edges = only(edges)
phantomedge = edges[end] # to bring step back to baseline
edges = vcat(edges, phantomedge)
z = zero(eltype(weights))
heights = vcat(z, weights, z)
(edges, heights)
else
(map(midpoints, edges)..., weights)
end
return positional, named
end

N = length(input.positional)
label = h.normalization == :none ? "count" : string(h.normalization)
labels = set(output.labels, N+1 => label)
attributes = if N == 1
attributes = if plottype == BarPlot
set(output.attributes, :gap => 0, :dodge_gap => 0)
else
output.attributes
end
default_plottype = categoricalplottypes[N]
plottype = Makie.plottype(output.plottype, default_plottype)
return ProcessedLayer(output; plottype, labels, attributes)
end

Expand Down
40 changes: 26 additions & 14 deletions test/reference_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ reftest("barplot cat color palette") do
draw(scales(Color = (; palette = :Set1_3)))
end

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

Expand Down Expand Up @@ -244,6 +244,18 @@ reftest("histogram stack") do
draw(specs)
end

reftest("histogram stairs cat color") do
df = (x=[sin.(1:500); sin.(1:500) .* 2], z=repeat(["a", "b"], inner = 500))
specs = data(df) * mapping(:x, layout=:z, color = :z) * visual(Stairs) * histogram()
draw(specs)
end

reftest("histogram scatter cat color") do
df = (x=[sin.(1:500); sin.(1:500) .* 2], z=repeat(["a", "b"], inner = 500))
specs = data(df) * mapping(:x, layout=:z, color = :z) * visual(Scatter) * histogram()
draw(specs)
end

reftest("histogram 2d") do
df = (x=sin.(1:300), y=cos.(1:300))
specs = data(df) * mapping(:x, :y) * histogram()
Expand Down Expand Up @@ -736,15 +748,15 @@ function presorted_plot(; with_missing::Bool)
end
group = ["2", "3", "1", "1", "3", "2"]
some_value = sort(exp.(sin.(1:6)))

df = (; countries, group, some_value)

m1 = mapping(:countries, :some_value, color = :group)
m2 = mapping(:countries => presorted, :some_value, color = :group)
m3 = mapping(:countries => presorted, :some_value, color = :group => presorted)

base = data(df) * visual(BarPlot, direction = :x)

f = Figure()
fg1 = draw!(f[1, 1], base * m1)
fg2 = draw!(f[2, 1], base * m2)
Expand Down Expand Up @@ -795,7 +807,7 @@ reftest("categorical color from continuous") do
f
end

reftest("title subtitle footnotes") do
reftest("title subtitle footnotes") do
spec = pregrouped(
fill(1:5, 6),
fill(11:15, 6),
Expand All @@ -816,7 +828,7 @@ reftest("title subtitle footnotes") do
)
end

reftest("title subtitle footnotes single unconstrained facet") do
reftest("title subtitle footnotes single unconstrained facet") do
spec = data((; x = 1:10, y = 11:20)) * mapping(:x, :y) * visual(Scatter)
draw(
spec;
Expand All @@ -831,7 +843,7 @@ reftest("title subtitle footnotes single unconstrained facet") do
)
end

reftest("title") do
reftest("title") do
spec = pregrouped(
fill(1:5, 6),
fill(11:15, 6),
Expand All @@ -847,7 +859,7 @@ reftest("title") do
)
end

reftest("title subtitle footnotes settings") do
reftest("title subtitle footnotes settings") do
spec = pregrouped(
fill(1:5, 6),
fill(11:15, 6),
Expand Down Expand Up @@ -877,10 +889,10 @@ reftest("title subtitle footnotes settings") do
),
axis = (; width = 100, height = 100)
)

end

reftest("title subtitle footnotes fontsize inherit") do
reftest("title subtitle footnotes fontsize inherit") do
spec = pregrouped(
fill(1:5, 6),
fill(11:15, 6),
Expand All @@ -902,7 +914,7 @@ reftest("title subtitle footnotes fontsize inherit") do
)
end

reftest("dodge barplot with errorbars") do
reftest("dodge barplot with errorbars") do
f = Figure()
df = (
x = [1, 1, 2, 2],
Expand Down Expand Up @@ -960,7 +972,7 @@ reftest("dodge scatter with rangebars") do
yhigh = cos.(range(0, 2pi, length = 20)) .+ 0.3,
dodge = repeat(["A", "B"], 10)
)

f = Figure()
spec1 = data(df) * (mapping(:x, :y, dodge_x = :dodge, color = :dodge) * visual(Scatter) + mapping(:x, :ylow, :yhigh, dodge_x = :dodge, color = :dodge) * visual(Rangebars))
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))
Expand All @@ -974,10 +986,10 @@ end
reftest("manual legend labels in visual") do
df_subjects = (; x = repeat(1:10, 10), y = cos.(1:100), id = repeat(1:10, inner = 10))
df_func = (; x = range(1, 10, length = 20), y = cos.(range(1, 10, length = 20)))

spec1 = data(df_subjects) * mapping(:x, :y, group = :id => nonnumeric) * visual(Lines, linestyle = :dash, color = (:black, 0.2), label = "Subject data")
spec2 = data(df_func) * mapping(:x, :y) * (visual(Lines, color = :tomato) + visual(Scatter, markersize = 12, color = :tomato, strokewidth = 2)) * visual(label = L"\cos(x)")

draw(spec1 + spec2)
end

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

spec2 = data((; x = 1:10, y = cos.(1:10) .+ 2)) * mapping(:x, :y) * visual(Scatter, color = :purple, label = "Scatter")

f = Figure()
fg = draw!(f[1, 1], spec1 + spec2)
legend!(f[1, 2], fg)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 60cb12c

Please sign in to comment.