diff --git a/docs/src/api.md b/docs/src/api.md index c297a80..e686d16 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -50,6 +50,15 @@ ridgeplot ridgeplot(boot) ``` +## Ridge 2D Plots + +```@docs +ridge2d +``` + +```@example Coefplot +ridge2d(boot) +``` ## Random effects and group-level predictions diff --git a/src/MixedModelsMakie.jl b/src/MixedModelsMakie.jl index b3470c4..e1e1b50 100644 --- a/src/MixedModelsMakie.jl +++ b/src/MixedModelsMakie.jl @@ -24,6 +24,8 @@ export RanefInfo, qqcaterpillar!, ranefinfo, ranefinfotable, + ridge2d, + ridge2d!, ridgeplot, ridgeplot!, shrinkageplot, @@ -40,6 +42,7 @@ include("caterpillar.jl") include("coefplot.jl") include("profile.jl") include("ridge.jl") +include("ridge2d.jl") include("xyplot.jl") include("recipes.jl") diff --git a/src/ridge2d.jl b/src/ridge2d.jl new file mode 100644 index 0000000..6a611e7 --- /dev/null +++ b/src/ridge2d.jl @@ -0,0 +1,40 @@ +function _ridge2d_panel!(ax::Axis, i::Int, j::Int, cnames::Vector{Symbol}, tbl) + x = Tables.getcolumn(tbl, cnames[j]) + y = Tables.getcolumn(tbl, cnames[i]) + dens = kde((x, y)) + scatter!(ax, x, y; color=:black, alpha=0.2) + plt = contour!(ax, collect(dens.x), collect(dens.y), dens.density; + color=:green, linewidth=3, + labelsize=30, labels=false) # reference points + + return plt +end + +""" + ridge2d!(f::Union{Makie.FigureLike,Makie.GridLayout}, bs::MixedModelBootstrap; + ptype=:β) + +Plot pairwise bivariate scatter plots with overlain densities for a bootstrap sample. + + +`ptype` specifies the set of parameters to examine, e.g. `:β`, `:σ`, `:ρ`. +""" +function ridge2d!(f::Union{Makie.FigureLike,Makie.GridLayout}, bs::MixedModelBootstrap; + ptype=:β) + tbl = bs.tbl + cnames = [string(x) for x in propertynames(tbl)[2:end]] + filter!(startswith(string(ptype)), cnames) + isempty(cnames) && + throw(ArgumentError("No parameters $ptype found.")) + length(cnames) == 1 && + throw(ArgumentError("Only 1 $ptype-paramater found: 2D plots require at least 2.")) + splomaxes!(f, cnames, _ridge2d_panel!, Symbol.(cnames), tbl) + return f +end + +"""$(@doc ridge2d!)""" +function ridge2d(bs::MixedModelBootstrap, args...; kwargs...) + f = Figure(; resolution=(1000, 1000)) # use an aspect ratio of 1 for the whole figure + + return ridge2d!(f, bs, args...; kwargs...) +end diff --git a/test/runtests.jl b/test/runtests.jl index 2bd827c..5157ccb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -36,8 +36,8 @@ m2 = fit(MixedModel, (1 + spkr | item)), MixedModels.dataset(:kb07); progress) -b1 = parametricbootstrap(MersenneTwister(42), 100, m1; hide_progress=!progress) - +b1 = parametricbootstrap(MersenneTwister(42), 500, m1; progress, + optsum_overrides=(; ftol_rel=1e-6)) g1 = fit(MixedModel, @formula(r2 ~ 1 + anger + gender + btype + situ + (1 | subj) + (1 + gender | item)), @@ -141,6 +141,15 @@ end save(joinpath(OUTDIR, "ridge_sleepstudy.png"), f) end +@testset "ridge2d" begin + @test_throws(ArgumentError("No parameters x found."), + ridge2d(b1; ptype=:x)) + @test_throws(ArgumentError("Only 1 ρ-paramater found: 2D plots require at least 2."), + ridge2d(b1; ptype=:ρ)) + save(joinpath(OUTDIR, "ridge2d_beta.png"), ridge2d(b1)) + save(joinpath(OUTDIR, "ridge2d_sigma.png"), ridge2d(b1; ptype=:σ)) +end + @testset "shrinkageplot" begin f = shrinkageplot(m1) save(joinpath(OUTDIR, "shrinkage_sleepstudy.png"), f)