Skip to content

Commit

Permalink
support custom colors in caterpillar and shrinkage plots (#74)
Browse files Browse the repository at this point in the history
* support custom colors in caterpillar plots

* patch bump

* YAS

* custom colors in shrinkage plots
  • Loading branch information
palday authored Jul 7, 2023
1 parent 4ad4aa2 commit 18e4089
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MixedModelsMakie"
uuid = "b12ae82c-6730-437f-aff9-d2c38332a376"
authors = ["Phillip Alday <[email protected]>", "Douglas Bates <[email protected]>", "contributors"]
version = "0.3.23"
version = "0.3.24"

[deps]
BSplineKit = "093aae92-e908-43d7-9660-e50ee39d5a0a"
Expand Down
42 changes: 30 additions & 12 deletions src/caterpillar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,12 @@ end

"""
caterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, r::RanefInfo;
orderby=1, cols::Union{Nothing,AbstractVector}=nothing)
orderby=1, cols::Union{Nothing,AbstractVector}=nothing,
dotcolor=(:red, 0.2), barcolor=:black)
caterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, m::LinearMixedModel,
gf::Symbol=first(fnames(m)); orderby=1, cols::Union{Nothing,AbstractVector}=nothing)
gf::Symbol=first(fnames(m)); orderby=1,
cols::Union{Nothing,AbstractVector}=nothing,
dotcolor=(:red, 0.2), barcolor=:black)
Add Axes of a caterpillar plot from `r` to `f`.
Expand All @@ -102,7 +105,8 @@ specifying `cols`, either by indices or term names.
`orderby` is the ``n``th column of the columns specified by `cols`.
"""
function caterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, r::RanefInfo;
orderby=1, cols::Union{Nothing,AbstractVector}=nothing)
orderby=1, cols::Union{Nothing,AbstractVector}=nothing,
dotcolor=(:red, 0.2), barcolor=:black)
cols = something(cols, axes(r.cnames, 1))
cols = _cols_to_idx(r.cnames, cols)
rr = view(r.ranef, :, cols)
Expand All @@ -114,8 +118,8 @@ function caterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, r::RanefInfo;
linkyaxes!(axs...)
for (j, ax) in enumerate(axs)
xvals = view(rr, ord, j)
scatter!(ax, xvals, y; color=(:red, 0.2))
errorbars!(ax, xvals, y, 1.960 * view(sd, ord, j); direction=:x)
scatter!(ax, xvals, y; color=dotcolor)
errorbars!(ax, xvals, y, 1.960 * view(sd, ord, j); direction=:x, color=barcolor)
ax.xlabel = cn[j]
ax.yticks = y
j > 1 && hideydecorations!(ax; grid=false)
Expand All @@ -130,7 +134,9 @@ function caterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, m::MixedModel
end

"""
caterpillar(m::LinearMixedModel, gf::Symbol; orderby=1, cols::Union{Nothing,AbstractVector}=nothing)
caterpillar(m::LinearMixedModel, gf::Symbol; orderby=1,
cols::Union{Nothing,AbstractVector}=nothing,
dotcolor=(:red, 0.2), barcolor=:black)
Returns a `Figure` of a "caterpillar plot" of the random-effects means and prediction intervals
Expand All @@ -147,15 +153,21 @@ specifying `cols`, either by indices or term names.
!!! note
`orderby` is the ``n``th column of the columns specified by `cols`.
See also [`caterpillar!`](@ref)
"""
function caterpillar(m::MixedModel, gf::Symbol=first(fnames(m)); kwargs...)
return caterpillar!(Figure(; resolution=(1000, 800)), m, gf; kwargs...)
end

"""
qqcaterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, r::RanefInfo; cols::Union{Nothing,AbstractVector}=nothing)
qqcaterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, r::RanefInfo;
cols::Union{Nothing,AbstractVector}=nothing,
dotcolor=(:red, 0.2), barcolor=:black)
qqcaterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, m::LinearMixedModel,
gf::Symbol=first(fnames(m)); cols::Union{Nothing,AbstractVector}=nothing)
gf::Symbol=first(fnames(m));
cols::Union{Nothing,AbstractVector}=nothing,
dotcolor=(:red, 0.2), barcolor=:black)
Update the figure with a caterpillar plot with the vertical axis on the Normal() quantile scale.
Expand All @@ -168,7 +180,8 @@ Setting `orderby=nothing` will disable sorting, i.e. return the levels in the
order they are stored in.
"""
function qqcaterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, r::RanefInfo;
cols::Union{Nothing,AbstractVector}=nothing)
cols::Union{Nothing,AbstractVector}=nothing,
dotcolor=(:red, 0.2), barcolor=:black)
cols = something(cols, axes(r.cnames, 1))
cols = _cols_to_idx(r.cnames, cols)
cn, rr = r.cnames, r.ranef
Expand All @@ -180,8 +193,9 @@ function qqcaterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, r::RanefInf
xvals = rr[:, k]
ord = sortperm(xvals)
xvals = xvals[ord]
scatter!(ax, xvals, y; color=(:red, 0.2))
errorbars!(ax, xvals, y, 1.960 * view(r.stddev, ord, k); direction=:x)
scatter!(ax, xvals, y; color=dotcolor)
errorbars!(ax, xvals, y, 1.960 * view(r.stddev, ord, k); direction=:x,
color=barcolor)
ax.xlabel = string(cn[k])
j > 1 && hideydecorations!(ax; grid=false)
end
Expand All @@ -194,12 +208,16 @@ function qqcaterpillar!(f::Union{Makie.FigureLike,Makie.GridLayout}, m::MixedMod
end

"""
qqcaterpillar(m::LinearMixedModel, gf::Symbol=first(fnames(m)); cols::Union{Nothing,AbstractVector}=nothing, orderby=1)
qqcaterpillar(m::LinearMixedModel, gf::Symbol=first(fnames(m));
cols::Union{Nothing,AbstractVector}=nothing, orderby=1,
dotcolor=(:red, 0.2), barcolor=:black)
Returns a `Figure` of a "qq-caterpillar plot" of the random-effects means and prediction intervals.
The display can be restricted to a subset of random effects associated with a grouping variable by
specifying `cols`, either by indices or term names.
See also [`qqcaterpillar!`](@ref).
"""
function qqcaterpillar(m::MixedModel, gf::Symbol=first(fnames(m)); kwargs...)
return qqcaterpillar!(Figure(; resolution=(1000, 800)), m, gf; kwargs...)
Expand Down
26 changes: 18 additions & 8 deletions src/shrinkage.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ function getellipsepoints(cx, cy, radius, lambda)
end

function _shrinkage_panel!(ax::Axis, i::Int, j::Int, reref, reest, λ;
ellipse::Bool, ellipse_scale::Real, n_ellipse::Integer)
ellipse::Bool, ellipse_scale::Real, n_ellipse::Integer,
shrunk_dotcolor, ref_dotcolor,
ellipse_color, ellipse_linestyle)
x, y = view(reref, j, :), view(reref, i, :)
u, v = view(reest, j, :), view(reest, i, :)
scatter!(ax, x, y; color=(:red, 0.25)) # reference points
scatter!(ax, x, y; color=ref_dotcolor) # reference points
arrows!(ax, x, y, u .- x, v .- y) # first so arrow heads don't obscure pts
plt = scatter!(ax, u, v; color=(:blue, 0.25)) # conditional means at estimates
plt = scatter!(ax, u, v; color=shrunk_dotcolor) # conditional means at estimates
if ellipse
# force computation of current limits
autolimits!(ax)
Expand All @@ -26,7 +28,7 @@ function _shrinkage_panel!(ax::Axis, i::Int, j::Int, reref, reest, λ;
rad_inner = 0
for radius in LinRange(rad_inner, rad_outer, n_ellipse + 1)
ex, ey = getellipsepoints(radius, cho)
lines!(ax, ex, ey; color=:green, linestyle=:dash)
lines!(ax, ex, ey; color=ellipse_color, linestyle=ellipse_linestyle)
end
# preserve the limits from before the ellipse
limits!(ax, lims)
Expand All @@ -35,8 +37,12 @@ function _shrinkage_panel!(ax::Axis, i::Int, j::Int, reref, reest, λ;
end

"""
shrinkageplot!(f::Union{Makie.FigureLike,Makie.GridLayout}, m::MixedModel, gf::Symbol=first(fnames(m)), θref;
ellipse=false, ellipse_scale=1, n_ellipse=5, cols::Union{Nothing,AbstractVector}=nothing)
shrinkageplot!(f::Union{Makie.FigureLike,Makie.GridLayout}, m::MixedModel,
gf::Symbol=first(fnames(m)), θref;
ellipse=false, ellipse_scale=1, n_ellipse=5,
cols::Union{Nothing,AbstractVector}=nothing,
shrunk_dotcolor=(:blue, 0.25), ref_dotcolor=(:red, 0.25),
ellipse_color=:green, ellipse_linestyle=:dash)
Return a scatter-plot matrix of the conditional means, b, of the random effects for grouping factor `gf`.
Expand All @@ -63,7 +69,9 @@ function shrinkageplot!(f::Union{Makie.FigureLike,Makie.GridLayout},
m.optsum.initial;
ellipse::Bool=false, ellipse_scale::Real=1,
n_ellipse::Integer=5,
cols::Union{Nothing,AbstractVector}=nothing) where {T}
cols::Union{Nothing,AbstractVector}=nothing,
shrunk_dotcolor=(:blue, 0.25), ref_dotcolor=(:red, 0.25),
ellipse_color=:green, ellipse_linestyle=:dash) where {T}
reind = findfirst(==(gf), fnames(m)) # convert the symbol gf to an index
if isnothing(reind)
throw(ArgumentError("gf=$gf is not one of the grouping factor names, $(fnames(m))"))
Expand All @@ -82,7 +90,9 @@ function shrinkageplot!(f::Union{Makie.FigureLike,Makie.GridLayout},
cnames = view(r.cnames, cols)

splomaxes!(f, cnames, _shrinkage_panel!,
reref, reest, λ; ellipse, ellipse_scale, n_ellipse)
reref, reest, λ; ellipse, ellipse_scale, n_ellipse,
shrunk_dotcolor, ref_dotcolor,
ellipse_color, ellipse_linestyle)

return f
end
Expand Down

2 comments on commit 18e4089

@palday
Copy link
Owner Author

@palday palday commented on 18e4089 Jul 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/87056

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.3.24 -m "<description of version>" 18e408997399403082a3aacdb295dce106ba8d2d
git push origin v0.3.24

Please sign in to comment.