# Errorline like plot for histograms

**URL:** https://discourse.julialang.org/t/errorline-like-plot-for-histograms/113911
**Category:** Visualization
**Tags:** plotting, statsplots, makie
**Created:** [May 6, 2024, 2:29pm UTC](https://discourse.julialang.org/t/errorline-like-plot-for-histograms/113911 "2024-05-06T14:29:46Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![dmetivie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmetivie/32/6926_2.png) [@dmetivie](https://discourse.julialang.org/u/dmetivie)
#### Post date: [May 6, 2024, 2:29pm UTC](https://discourse.julialang.org/t/errorline-like-plot-for-histograms/113911/1 "2024-05-06T14:29:46Z")

</div>

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

```julia
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

```julia
@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

```

```julia
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)

---

<div class="post-metadata">

### Author: ![asinghvi17](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/asinghvi17/32/8272_2.png) [@asinghvi17](https://discourse.julialang.org/u/asinghvi17)
#### Post date: [May 6, 2024, 2:39pm UTC](https://discourse.julialang.org/t/errorline-like-plot-for-histograms/113911/2 "2024-05-06T14:39:47Z")

</div>

Hmm, it looks like you want something like a [fan plot](https://github.com/MakieOrg/Makie.jl/issues/1995)?

If all you want is some plot at each x coordinate, that’s pretty easy to do via Makie’s SpecAPI.

---

<div class="post-metadata">

### Author: ![dmetivie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmetivie/32/6926_2.png) [@dmetivie](https://discourse.julialang.org/u/dmetivie)
#### Post date: [May 6, 2024, 10:00pm UTC](https://discourse.julialang.org/t/errorline-like-plot-for-histograms/113911/3 "2024-05-06T22:00:21Z")

</div>

If I understand, what you are refering to is equivalent (maybe a bit fancier) to [errorline](https://github.com/JuliaPlots/StatsPlots.jl?tab=readme-ov-file#errorline) in StatsPlots?  
What I would like is build a receipt to convert a matrix `pxN` into a `p` histograms and then represent with fan plot or errorlines. Ideally, this receipt would accept the same keywords as histograms and errolines.

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [May 7, 2024, 1:08am UTC](https://discourse.julialang.org/t/errorline-like-plot-for-histograms/113911/4 "2024-05-07T01:08:24Z")

</div>

Do you have a reference to a visualization in the wild? in #hep we take envelope of histograms very often but I haven’t seen a very canonical way to visualize the “envelope”

Usually I think what people do is after take per-bin minimal/maximum, we simply plot the final spread as the error using shading or something, see the bottom of this example page: [Makie Plotting · FHist.jl](https://moelf.github.io/FHist.jl/dev/notebooks/makie_plotting/)

---

<div class="post-metadata">

### Author: ![dmetivie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmetivie/32/6926_2.png) [@dmetivie](https://discourse.julialang.org/u/dmetivie)
#### Post date: [May 14, 2024, 2:35pm UTC](https://discourse.julialang.org/t/errorline-like-plot-for-histograms/113911/5 "2024-05-14T14:35:21Z")

</div>

Unfortunately, I don’t find a good reference.

I agree that the per bin min/max is what people do. I was just looking for a method to do that. I tried FHist.jl but could not get exactly what I wanted with StackHist (which BTW error when staking more than 7 hist)

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [May 14, 2024, 8:53pm UTC](https://discourse.julialang.org/t/errorline-like-plot-for-histograms/113911/6 "2024-05-14T20:53:56Z")

</div>

> [@dmetivie](#):
>
> which BTW error when staking more than 7 hist

that’s because the `Wong()` color only has 7 colors, if you need more you need to supply the colors manually.

---

<div class="post-metadata">

### Author: ![dmetivie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmetivie/32/6926_2.png) [@dmetivie](https://discourse.julialang.org/u/dmetivie)
#### Post date: [June 13, 2024, 2:32pm UTC](https://discourse.julialang.org/t/errorline-like-plot-for-histograms/113911/7 "2024-06-13T14:32:53Z")

</div>

I think I got my `Plots.jl` recipe to work in case someone need that.  
Mostly permutation of the input was needed.

```julia
# grouped histogram
@userplot ErrorLineHist

Plots.group_as_matrix(g::ErrorLineHist) = true

@recipe function f(p::ErrorLineHist)
    _, v = StatsPlots.grouped_xy(p.args...)
    v = permutedims(v)
    bins = get(plotattributes, :bins, :auto)
    normed = get(plotattributes, :normalize, false)
    weights = get(plotattributes, :weights, nothing)

    vs = filter.(isfinite, (v,))
    edges = Plots._hist_edges(vs, bins)
    nbins = length(edges[1]) .- 1
    x = map(i -> (edges[1][i] + edges[1][i + 1]) / 2, 1:nbins)

    ngroups = size(v, 2)

    # compute weights (frequencies) by group using those edges
    y = zeros(nbins, ngroups)
    for i in 1:ngroups
        v_i = filter(isfinite, v[:, i])
        w_i = weights #isnothing(weights) ? nothing : weights[groupinds]
        h_i = Plots._make_hist((v_i,), edges; normed = normed, weights = w_i)
        y[:, i] += h_i.weights
    end

    StatsPlots.ErrorLine((x, y))
end

```

Then this works i.e. enveloppe is the same as all plots.

```julia
dist = Exponential()
N = 100 # number of sample used in each histogram
N_hist = 1000 # number of histogram
yc = rand(dist, N_hist, N)

edges = 0:0.05:11.1 # to guarantee same bins (histogram looks different for different bins)
begin 
    p = plot()
    [stephist!(y, label = :none, c = :gray, alpha = 0.1, norm = :pdf, bins = edges) for y in eachrow(yc)]
    errorlinehist!(yc, label = "it works", errortype = :percentile, percentiles = [0,100], fillalpha = 0.1, normalize = :pdf, bins = edges)
end

```
