Creating boxplot with or without notch (Plots, StatsPlots)

I am trying to create a plot which contains 3 boxplots.
First one has 21 data point, second one has 26 and third one has 21 data points.
I can create each one seperately using StatsPlots library. When I try to combine them I am getting error.
Here is the data and output I got:

using StatsPlots
a = rand(21)*600
b = rand(26)*600
c = rand(21)*600
bp1 = boxplot(["Tier 1"],a,leg=false;notch=true,ylim=(0,600))
bp2 = boxplot(["Tier 2"],b,leg=false;notch=true,ylim=(0,600))
bp3 = boxplot(["Tier 3"],c,leg=false;notch=true,ylim=(0,600))
StatsPlots.plot(bp1, bp2, bp3)

image

When I run:

boxplot(["Tier 1"],a,leg=false;notch=true,ylim=(0,600))
boxplot!(["Tier 2"],b,leg=false;notch=true,ylim=(0,600))
boxplot!(["Tier 3"],c,leg=false;notch=true,ylim=(0,600))

I am getting this error:
BoundsError: attempt to access 1-element Array{Float64,1} at index [2]

Stacktrace:
[1] getindex(::Array{Float64,1}, ::Int64) at ./array.jl:731
[2] macro expansion at /home/ec2-user/.julia/packages/StatsPlots/HQ166/src/boxplot.jl:51 [inlined]
[3] apply_recipe(::Dict{Symbol,Any}, ::Type{Val{:boxplot}}, ::Array{String,1}, ::Array{Float64,1}, ::Nothing) at /home/ec2-user/.julia/packages/RecipesBase/Uz5AO/src/RecipesBase.jl:275
[4] _process_seriesrecipe(::Plots.Plot{Plots.GRBackend}, ::Dict{Symbol,Any}) at /home/ec2-user/.julia/packages/Plots/qh1wV/src/pipeline.jl:408
[5] macro expansion at ./logging.jl:318 [inlined]
[6] _plot!(::Plots.Plot{Plots.GRBackend}, ::Dict{Symbol,Any}, ::Tuple{Array{String,1},Array{Float64,1}}) at /home/ec2-user/.julia/packages/Plots/qh1wV/src/plot.jl:171
[7] plot!#137(::Base.Iterators.Pairs{Symbol,Any,NTuple{4,Symbol},NamedTuple{(:leg, :notch, :ylim, :seriestype),Tuple{Bool,Bool,Tuple{Int64,Int64},Symbol}}}, ::Function, ::Plots.Plot{Plots.GRBackend}, ::Array{String,1}, ::Vararg{Any,N} where N) at /home/ec2-user/.julia/packages/Plots/qh1wV/src/plot.jl:158
[8] (::getfield(RecipesBase, Symbol(“#kw#plot!”)))(::NamedTuple{(:leg, :notch, :ylim, :seriestype),Tuple{Bool,Bool,Tuple{Int64,Int64},Symbol}}, ::typeof(plot!), ::Plots.Plot{Plots.GRBackend}, ::Array{String,1}, ::Vararg{Any,N} where N) at ./none:0
[9] plot!#136(::Base.Iterators.Pairs{Symbol,Any,NTuple{4,Symbol},NamedTuple{(:leg, :notch, :ylim, :seriestype),Tuple{Bool,Bool,Tuple{Int64,Int64},Symbol}}}, ::Function, ::Array{String,1}, ::Vararg{Any,N} where N) at /home/ec2-user/.julia/packages/Plots/qh1wV/src/plot.jl:150
[10] (::getfield(RecipesBase, Symbol(“#kw#plot!”)))(::NamedTuple{(:leg, :notch, :ylim, :seriestype),Tuple{Bool,Bool,Tuple{Int64,Int64},Symbol}}, ::typeof(plot!), ::Array{String,1}, ::Array{Float64,1}) at ./none:0
[11] #boxplot!#404(::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:leg, :notch, :ylim),Tuple{Bool,Bool,Tuple{Int64,Int64}}}}, ::Function, ::Array{String,1}, ::Vararg{Any,N} where N) at /home/ec2-user/.julia/packages/RecipesBase/Uz5AO/src/RecipesBase.jl:369
[12] (::getfield(Plots, Symbol(“#kw##boxplot!”)))(::NamedTuple{(:leg, :notch, :ylim),Tuple{Bool,Bool,Tuple{Int64,Int64}}}, ::typeof(boxplot!), ::Array{String,1}, ::Vararg{Any,N} where N) at ./none:0
[13] top-level scope at In[10]:2

One more issue is that altough I am using StatsPlots, I am getting this warning:

┌ Warning: seriestype boxplot has been moved to StatPlots.  To use: `Pkg.add("StatPlots"); using StatPlots`
└ @ Plots /home/ec2-user/.julia/packages/Plots/qh1wV/src/args.jl:1054
┌ Warning: seriestype boxplot has been moved to StatPlots.  To use: `Pkg.add("StatPlots"); using StatPlots`
└ @ Plots /home/ec2-user/.julia/packages/Plots/qh1wV/src/args.jl:1054
┌ Warning: seriestype boxplot has been moved to StatPlots.  To use: `Pkg.add("StatPlots"); using StatPlots`
└ @ Plots /home/ec2-user/.julia/packages/Plots/qh1wV/src/args.jl:1054
┌ Warning: seriestype boxplot has been moved to StatPlots.  To use: `Pkg.add("StatPlots"); using StatPlots`
└ @ Plots /home/ec2-user/.julia/packages/Plots/qh1wV/src/args.jl:1054

The first issue is Boxplot and violin broken · Issue #198 · JuliaPlots/StatsPlots.jl · GitHub - essentially the recipe broke when we tried to add some nice new functionality.
The other is your Plots version being out of date, most likely.

I have updated Plots and now even this is not working.
StatsPlots.plot(bp1, bp2, bp3)

UndefVarError: warn not defined

Stacktrace:
 [1] macro expansion at /home/ec2-user/.julia/packages/StatsPlots/HQ166/src/boxplot.jl:45 [inlined]
 [2] apply_recipe(::Dict{Symbol,Any}, ::Type{Val{:boxplot}}, ::Array{String,1}, ::Array{Float64,1}, ::Nothing) at /home/ec2-user/.julia/packages/RecipesBase/Uz5AO/src/RecipesBase.jl:275
 [3] _process_seriesrecipe(::Plots.Plot{Plots.GRBackend}, ::Dict{Symbol,Any}) at /home/ec2-user/.julia/packages/Plots/UQI78/src/pipeline.jl:408
 [4] macro expansion at ./logging.jl:318 [inlined]
 [5] _plot!(::Plots.Plot{Plots.GRBackend}, ::Dict{Symbol,Any}, ::Tuple{Array{String,1},Array{Float64,1}}) at /home/ec2-user/.julia/packages/Plots/UQI78/src/plot.jl:171
 [6] #plot#136(::Base.Iterators.Pairs{Symbol,Any,NTuple{4,Symbol},NamedTuple{(:leg, :notch, :ylim, :seriestype),Tuple{Bool,Bool,Tuple{Int64,Int64},Symbol}}}, ::Function, ::Array{String,1}, ::Vararg{Any,N} where N) at /home/ec2-user/.julia/packages/Plots/UQI78/src/plot.jl:57
 [7] (::getfield(RecipesBase, Symbol("#kw##plot")))(::NamedTuple{(:leg, :notch, :ylim, :seriestype),Tuple{Bool,Bool,Tuple{Int64,Int64},Symbol}}, ::typeof(plot), ::Array{String,1}, ::Array{Float64,1}) at ./none:0
 [8] #boxplot#412(::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:leg, :notch, :ylim),Tuple{Bool,Bool,Tuple{Int64,Int64}}}}, ::Function, ::Array{String,1}, ::Vararg{Any,N} where N) at /home/ec2-user/.julia/packages/RecipesBase/Uz5AO/src/RecipesBase.jl:368
 [9] (::getfield(Plots, Symbol("#kw##boxplot")))(::NamedTuple{(:leg, :notch, :ylim),Tuple{Bool,Bool,Tuple{Int64,Int64}}}, ::typeof(boxplot), ::Array{String,1}, ::Vararg{Any,N} where N) at ./none:0
 [10] top-level scope at In[11]:4

Is there any other package I can use working with julia 1?

Gadfly has non-notched boxplots, and works with Julia 1.x.

There is a PR to do dodged boxplots.

Hi, that warn thing is correctly a remnant from the 0.6 → 1.0 release on StatsPlots. I’ve fixed it on master, it’s caused by some irregularity in the code generating the notch size for your data (it’s simply that difference between the 3rd and 4th quartile is so small that there isn’t space to draw a regularly shaped notch. I’ll look at changing the default notch depth). But otherwise, StatsPlots and Plots have been working on 1.0 since 1 day after the 1.0 release.

What happened is that we added dodged (grouped) boxplots to the functionality, but it turns out it broke a rarely used syntax for non-grouped boxplots, which is the one you are using. The ideomatic boxplot syntax, which works and always have worked, is to use a long-format (tidy) format, just like in DataFrames:

tier = [repeat(["Tier 1"], 21); repeat(["Tier 2"], 26); repeat(["Tier 3"], 21)]
boxplot(tier, [a;b;c])

I’d expect Gadfly to expect you to use that syntax as well.

Still, sufficiently many appear to be using wide format plots to StatsPlots and experience errors, so that I’ve decided we need to remove the grouped boxplot functionality again, and look for a different implementation. So I’ve reverted that PR and pushed a new release (v0.10.1).

Thank you, that’s what I was trying to do. It looks nice now.

1 Like

@mkborregaard is this issue resolved in the current release of StatsPlots? I am trying to do the following and getting the attempt to access 1-element array error:

@df male_df violin(:genotype,:age, side=:right, marker=(0.2, :blue, stroke(0)), label=“Male”) <= works
@df female_df violin!(:genotype,:age, side=:left, marker=(0.2, :red, stroke(0)), label=“MFemale”) <= fails

I saw that v0.10.2 was released with groupedviolin. How can I use this feature to achieve the above split violin plot?

Thank you!

@mkborregaard I updated to v0.10.2 again and the problem was resolved. I am now able to graph split violin charts. Thank you for an excellent charting package!

1 Like