I would like to create an envelope plot for multiple histogram (input as matrix) something like what is done with errorline
in StatsPlots. (I did not find a Makie equivalent of errorline
).
Basically, what I want would look like
dist = Exponential()
N = 100 # number of sample used in each histogram
N_hist = 1000 # number of histogram
yc = rand(dist, N_hist, N)
begin
plot()
[stephist!(y, label = :none, c = :gray, alpha = 0.1, bins = 0:1:15) for y in eachrow(yc)]
plot!()
end
In this example, the “interval” is generated with each of the 1000 stephist lines. This is a bit heavy to display and it would be better to have a fill
between the min and max.
Using the erroline
I tried building a plot receipt but something is wrong
@userplot ErrorLineHist
Plots.group_as_matrix(g::ErrorLineHist) = true
@recipe function f(p::ErrorLineHist)
_, v = StatsPlots.grouped_xy(p.args...)
bins = get(plotattributes, :bins, :auto)
normed = get(plotattributes, :normalize, false)
weights = get(plotattributes, :weights, nothing)
# compute edges from ungrouped data
h = Plots._make_hist((vec(copy(v)),), bins; normed = normed, weights = weights)
nbins = length(h.weights)
edges = h.edges[1]
bar_width --> mean(map(i -> edges[i + 1] - edges[i], 1:nbins))
x = map(i -> (edges[i] + edges[i + 1]) / 2, 1:nbins)
ngroups = size(v, 2)
ntot = count(x -> !isnan(x), v)
# compute weights (frequencies) by group using those edges
y = fill(NaN, nbins, ngroups)
for i in 1:ngroups
v_i = filter(x -> !isnan(x), v[:, i])
w_i = isnothing(weights) ? nothing : weights[groupinds]
h_i = Plots._make_hist((v_i,), h.edges; normed = false, weights = w_i)
StatsBase.normalize!(h_i, mode = Plots._hist_norm_mode(normed))
y[:, i] .= h_i.weights
end
StatsPlots.ErrorLine((x, y))
end
errorlinehist!(yc, label = "not quite that")
Not sure what I missed. Does someone have an idea? (or know if similar feature is already implemented somewhere)?
(uploading does not work currently for me)