# Showing percentage different between bar of grouped bar chart in Plotly

**URL:** https://discourse.julialang.org/t/showing-percentage-different-between-bar-of-grouped-bar-chart-in-plotly/105681
**Category:** General Usage
**Tags:** plotting, plotlyjs
**Created:** [November 2, 2023, 8:03am UTC](https://discourse.julialang.org/t/showing-percentage-different-between-bar-of-grouped-bar-chart-in-plotly/105681 "2023-11-02T08:03:49Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![nnguyengiatan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nnguyengiatan/32/48837_2.png) [@nnguyengiatan](https://discourse.julialang.org/u/nnguyengiatan)
#### Post date: [November 2, 2023, 8:03am UTC](https://discourse.julialang.org/t/showing-percentage-different-between-bar-of-grouped-bar-chart-in-plotly/105681/1 "2023-11-02T08:03:49Z")

</div>

Hello all,  
As you can see in the example below, I would like to label my grouped bar chart with the % differential between each group of bars. Could anyone point me to documentation or examples that would cover that?

Here is the dataframe:

```julia
df_hr = DataFrame(
    year = [2017, 2018, 2019, 2020, 2021, 2017, 2018, 2019, 2020, 2021],
    mean_hrpaid = [3.7, 4.08, 4.77, 4.69, 5.04, 6.73, 6.9, 6.91, 6.48, 6.3],
    type = ["Countryside", "Countryside", "Countryside", "Countryside", "Countryside", "SIB", "SIB", "SIB", "SIB", "SIB"]
)

```

I got the chart with the following code:

```julia
p_hr = Plot(df_hr, 
                x=:year, 
                y=:mean_hrpaid,
                color=:type,
                text=:mean_hrpaid,
                kind="bar",
                textposition="auto",
                labels=Dict(
                    :year => "Year",
                    :mean_hrpaid => "Monthly income (\$)",
                    :type => "Area",
                ),
                Layout(barmode = "group", 
                font_family = "Cambria",
                separators = ",",
                font = attr(size=17),
                legend = attr(
                    x=1,
                    y=1.02,
                    yanchor="bottom",
                    xanchor="right",
                    orientation="h"
                )
                )
)

```

Here is the example chart that I want to get:

 ![387594788_907801500725761_1709739992837264902_n](https://global.discourse-cdn.com/julialang/original/3X/c/6/c686ebd88c8478b4a4a41e88e965a6e715a50819.jpeg)  
Thank all!

---

<div class="post-metadata">

### Author: ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)
#### Post date: [November 2, 2023, 9:24am UTC](https://discourse.julialang.org/t/showing-percentage-different-between-bar-of-grouped-bar-chart-in-plotly/105681/2 "2023-11-02T09:24:40Z")

</div>

```julia-repl
julia> span(v) = round(100*(maximum(v) - minimum(v))/maximum(v); digits=2)

julia> df_change = combine(groupby(df_hr, :year), :mean_hrpaid => span => :percent_change)
5×2 DataFrame
 Row │ year percent_change 
     │ Int64 Float64        
─────┼───────────────────────
   1 │ 2017 45.0223
   2 │ 2018 40.8696
   3 │ 2019 30.9696
   4 │ 2020 27.6235
   5 │ 2021 20.0

```

Not sure how to add this to the plot directly however. The best way might be to just have a separate sublot:

```julia
p_ch = Plot(df_change, 
                x=:year, 
                y=:percent_change,
                text=:percent_change,
                kind="bar",
                textposition="auto",
                name="% change",
                labels=Dict(
                    :year => "Year",
                    :percent_change => "% change Monthly income (\$)",
                    :type => "Area",
                ),
                )
)

[ p_hr
  p_ch]

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/d/b/db47dc5fb176eb562c0658eef5c8a59af8399638.png)

---

<div class="post-metadata">

### Author: ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)
#### Post date: [November 3, 2023, 9:13pm UTC](https://discourse.julialang.org/t/showing-percentage-different-between-bar-of-grouped-bar-chart-in-plotly/105681/3 "2023-11-03T21:13:46Z")

</div>

> **code**
>
> ```julia
> julia> using CairoMakie, DataFrames
> 
> julia> df_hr = DataFrame(
> year = [2017, 2018, 2019, 2020, 2021, 2017, 2018, 2019, 2020, 2021],
> mh = [3.7, 4.08, 4.77, 4.69, 5.04, 6.73, 6.9, 6.91, 6.48, 6.3],
> type = ["Countryside", "Countryside", "Countryside", "Countryside", "Countryside", "SIB", "SIB", "SIB", "SIB", "SIB"]
> )
> 10×3 DataFrame
> Row │ year mh type        
> │ Int64 Float64 String      
> ─────┼─────────────────────────────
> 1 │ 2017 3.7 Countryside
> 2 │ 2018 4.08 Countryside
> 3 │ 2019 4.77 Countryside
> 4 │ 2020 4.69 Countryside
> 5 │ 2021 5.04 Countryside
> 6 │ 2017 6.73 SIB
> 7 │ 2018 6.9 SIB
> 8 │ 2019 6.91 SIB
> 9 │ 2020 6.48 SIB
> 10 │ 2021 6.3 SIB
> 
> julia> udf=unstack(df_hr,:year,:type,:mh)
> 5×3 DataFrame
> Row │ year Countryside SIB      
> │ Int64 Float64? Float64? 
> ─────┼──────────────────────────────
> 1 │ 2017 3.7 6.73
> 2 │ 2018 4.08 6.9
> 3 │ 2019 4.77 6.91
> 4 │ 2020 4.69 6.48
> 5 │ 2021 5.04 6.3
> 
> julia> span(sib,cs) = @. round(100*(sib - cs)/sib; digits=2)
> span (generic function with 1 method)
> 
> julia> transform!(udf,[[3,2]].=>[span, .-].=>[:deltapc, :delta])
> 5×5 DataFrame
> Row │ year Countryside SIB deltapc delta ⋯
> │ Int64 Float64? Float64? Float64 Float ⋯
> ─────┼───────────────────────────────────────────────
> 1 │ 2017 3.7 6.73 45.02 3. ⋯
> 2 │ 2018 4.08 6.9 40.87 2.  
> 3 │ 2019 4.77 6.91 30.97 2.  
> 4 │ 2020 4.69 6.48 27.62 1.  
> 5 │ 2021 5.04 6.3 20.0 1. ⋯
> 1 column omitted
> 
> julia> sdf=stack(udf, [2,3,5])
> 15×4 DataFrame
> Row │ year deltapc variable value            
> │ Int64 Float64 String Float64?
> ─────┼───────────────────────────────────────        
> 1 │ 2017 45.02 Countryside 3.7
> 2 │ 2018 40.87 Countryside 4.08
> 3 │ 2019 30.97 Countryside 4.77
> 4 │ 2020 27.62 Countryside 4.69
> 5 │ 2021 20.0 Countryside 5.04
> 6 │ 2017 45.02 SIB 6.73
> 7 │ 2018 40.87 SIB 6.9
> 8 │ 2019 30.97 SIB 6.91
> 9 │ 2020 27.62 SIB 6.48
> 10 │ 2021 20.0 SIB 6.3
> 11 │ 2017 45.02 delta 3.03
> 12 │ 2018 40.87 delta 2.82
> 13 │ 2019 30.97 delta 2.14
> 14 │ 2020 27.62 delta 1.79
> 15 │ 2021 20.0 delta 1.26
> 
> julia> sort!(sdf,:year)
> 15×4 DataFrame
> Row │ year deltapc variable value            
> │ Int64 Float64 String Float64?
> ─────┼───────────────────────────────────────        
> 1 │ 2017 45.02 Countryside 3.7
> 2 │ 2017 45.02 SIB 6.73
> 3 │ 2017 45.02 delta 3.03
> 4 │ 2018 40.87 Countryside 4.08
> 5 │ 2018 40.87 SIB 6.9
> 6 │ 2018 40.87 delta 2.82
> 7 │ 2019 30.97 Countryside 4.77
> 8 │ 2019 30.97 SIB 6.91
> 9 │ 2019 30.97 delta 2.14
> 10 │ 2020 27.62 Countryside 4.69
> 11 │ 2020 27.62 SIB 6.48
> 12 │ 2020 27.62 delta 1.79
> 13 │ 2021 20.0 Countryside 5.04
> 14 │ 2021 20.0 SIB 6.3
> 15 │ 2021 20.0 delta 1.26
> 
> julia> fig=Figure();
> 
> julia> ax = Axis(
> fig[2,1],
> ylabel = "Montly Income (\$)",
> xlabel = "Year"
> )
> Axis with 0 plots:
> 
> julia> bar_lbls=begin
> bl=[]
> for r in eachrow(udf)
> size_arr = "="^Int(trunc(r.delta))
> push!(bl,r.Countryside,r.SIB,"")
> end
> bl
> end
> 15-element Vector{Any}:
> 3.7
> 6.73
> ""
> 4.08
> 6.9
> ""
> 4.77
> 6.91
> ""
> 4.69
> 6.48
> ""
> 5.04
> 6.3
> ""
> 
> julia> barplot!(sdf.year, sdf.value,
> dodge = repeat([1, 2, 1],5),
> stack = repeat([1, 2, 3],5),
> color = repeat([1, 2, 3],5),
> colormap = [:red, :blue,:white],      
> bar_labels=bar_lbls,
> label_rotation= pi/2,
> label_offset=-75,
> label_size=repeat([20,20,15],5),      
> label_color=repeat([:white,:white,:blue],5),
> xticks = 2017:2021
> )
> Combined{Makie.barplot, Tuple{Vector{Point{2, Float32}}}}
> 
> julia> size_arr = @. "="^Int(trunc(udf.delta))       
> 5-element Vector{String}:
> "==="
> "=="
> "=="
> "="
> "="
> 
> julia> bl=@. "<"*size_arr *"| " *string(udf.deltapc)*"%"
> 5-element Vector{String}:
> "<===| 45.02%"
> "<==| 40.87%"
> "<==| 30.97%"
> "<=| 27.62%"
> "<=| 20.0%"
> 
> julia> text!(
> bl,
> position = Point2f.([2017,2018,2019,2020,2021].-0.2,5.8),
> color = :black,
> rotation= [pi/2,pi/2,pi/2,pi/2,pi/2], 
> align = (:center, :center)
> )
> MakieCore.Text{Tuple{Vector{String}}}
> 
> julia> labels = unique(sdf.variable)
> 3-element Vector{String}:
> "Countryside"
> "SIB"
> "delta"
> 
> julia> elements = [PolyElement(polycolor = cgrad(:tab10)[[1,2]][i]) for i in 1:2]
> 2-element Vector{PolyElement}:
> PolyElement(Attributes with 1 entry:
> polycolor => RGBA{Float64}(0.1216,0.4667,0.7059,1.0))
> PolyElement(Attributes with 1 entry:
> polycolor => RGBA{Float64}(1.0,0.498,0.0549,1.0))  
> 
> julia> el=[elements..., PolyElement(color=:black,markercolor = :transparent, polystrokecolor = :transparent, polypoints = Point{2, Float32}[[0.0, 0.4], [0.0, 0.6], [0.5, 0.6], [0.5,1.0], [1.0, 0.5],[0.5,0.0],[0.5,0.4]])]
> 3-element Vector{PolyElement}:
> PolyElement(Attributes with 1 entry:
> polycolor => RGBA{Float64}(0.1216,0.4667,0.7059,1.0))
> PolyElement(Attributes with 1 entry:
> polycolor => RGBA{Float64}(1.0,0.498,0.0549,1.0))  
> PolyElement(Attributes with 4 entries:
> markercolor => transparent
> polycolor => black
> polypoints => Point{2, Float32}[[0.0, 0.4], [0.0, 0.6], [0.5, 0.6], [0.5, 1.0], [1.0, 0.5], [0.5, 0.0], [0.5, 0.4]]
> polystrokecolor => transparent)
> 
> julia> Legend(fig[1,1], el, labels, orientation=:horizontal, tellwidth = false, tellheight = true)        
> Legend()
> 
> julia> fig
> 
> julia> save("normal.png", fig) # size = 800 x 600 px 
> CairoMakie.Screen{IMAGE}
> 
> ```

 ![normal](https://global.discourse-cdn.com/julialang/original/3X/a/7/a703e6d43a4144847b6876e3cbba6cdc36b37c52.png)

```julia
elements = [PolyElement(polycolor = [:red,:blue][[1,2]][i]) for i in 1:2]
pos=(udf.Countryside.+udf.SIB)./2
text!(
        bl,
        position = Point2f.([2017,2018,2019,2020,2021].-0.2,pos),
        color = :black,
        rotation= pi/2, # [pi/2,pi/2,pi/2,pi/2,pi/2],
        align = (:center, :center)
        )

```

 ![income](https://global.discourse-cdn.com/julialang/original/3X/1/e/1e883a15525d51282e104589727c12ae4a70fad4.png)

---

<div class="post-metadata">

### Author: ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)
#### Post date: [November 4, 2023, 1:33pm UTC](https://discourse.julialang.org/t/showing-percentage-different-between-bar-of-grouped-bar-chart-in-plotly/105681/4 "2023-11-04T13:33:26Z")

</div>

> **Summary**
>
> ```julia
> udf=unstack(df_hr,:year,:type,:mh)
> span(sib,cs) = @. round(100*(sib - cs)/sib; digits=2)
> 
> transform!(udf,[[3,2]].=>[span, .-].=>[:Deltapc, :Delta], 2=>identity=>:Cs2)
> 
> sdf=stack(udf, [2,3,5, 6])
> sort!(sdf,[:year,:variable])
> fig=Figure();
> ax = Axis(
> fig[1,1],
> ylabel = "Montly Income (\$)",
> xlabel = "Year",
> title= " Lustrum income",
> titlesize=20
> )
> bar_lbls=begin
> bl=[]
> for r in eachrow(udf)
> push!(bl,r.Countryside,"", string(trunc(Int, r.Deltapc))*"%",r.SIB)
> end
> bl
> end
> 
> barplot!(sdf.year, sdf.value,
> dodge = repeat([1, 2, 2, 3],5),
> stack = repeat([1, 2, 3, 4],5),
> color = repeat([1, 2, 3, 4],5),
> colormap = [:red, :white, :gray, :blue],
> bar_labels=bar_lbls,
> label_rotation= pi/2,
> label_offset=-75,
> # label_size=repeat([20,20,15],5),
> label_color=:white,
> xticks = 2017:2021
> )
> 
> labels = names(udf)[[2,4,3]]
> elements = [PolyElement(polycolor = [:red,:gray,:blue][[1,2,3]][i]) for i in 1:3]
> Legend(fig[1,2], elements, labels, orientation=:vertical, tellwidth = true, tellheight = false)
> fig
> save("lustrum income.png", fig) 
> 
> ```

 ![lustrum income](https://global.discourse-cdn.com/julialang/original/3X/8/8/8803d658144a9d876110a215bc9a8bc9aedf9a14.png)
