diff options
author | Ken Kellner <ken@kenkellner.com> | 2019-11-08 12:50:36 -0500 |
---|---|---|
committer | Ken Kellner <ken@kenkellner.com> | 2019-11-08 12:50:36 -0500 |
commit | ea71ba115f4821b8d89628d537bcfe9ca85d5a3d (patch) | |
tree | a302ec0920fc2c97a5db34a2415f364ff2ceca95 | |
parent | eb36fb97e2e993e7e6b9895c9d48ed85e4ea7e31 (diff) |
Add whiskerplot() and effectsplot()
-rw-r--r-- | Project.toml | 1 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | examples/example_occupancy.jl | 6 | ||||
-rw-r--r-- | src/Unmarked.jl | 4 | ||||
-rw-r--r-- | src/plots.jl | 101 |
5 files changed, 112 insertions, 2 deletions
diff --git a/Project.toml b/Project.toml index 4e79dbc..d2dc955 100644 --- a/Project.toml +++ b/Project.toml @@ -8,6 +8,7 @@ Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" +Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" NLSolversBase = "d41bc354-129a-5804-8e4c-c37616107c6c" Optim = "429524aa-4258-5aef-a3af-852621145aeb" @@ -12,7 +12,7 @@ using Unmarked, DataFrames ψ_formula = @formula(ψ~elev+forest); p_formula = @formula(p~precip+wind); β_truth = [0, -0.5, 1.2, -0.2, 0, 0.7]; -umd = simulate(Occu, ψ_formula, p_formula, [1000, 5], β_truth); +umd = simulate(Occu, ψ_formula, p_formula, (1000, 5), β_truth); #Fit the model fit = occu(ψ_formula, p_formula, umd) diff --git a/examples/example_occupancy.jl b/examples/example_occupancy.jl index 7017b82..ee49780 100644 --- a/examples/example_occupancy.jl +++ b/examples/example_occupancy.jl @@ -10,6 +10,12 @@ fit = occu(ψ_formula, p_formula, umd); hcat(coef(fit), β_truth) +#Plots +using Gadfly +set_default_plot_size(20cm, 20cm) +whiskerplot(fit) +effectsplot(fit) + #Prediction pr = predict(detection(fit)); diff --git a/src/Unmarked.jl b/src/Unmarked.jl index c30fa97..40d6ebe 100644 --- a/src/Unmarked.jl +++ b/src/Unmarked.jl @@ -5,6 +5,7 @@ using LinearAlgebra, DataFrames, Optim, NLSolversBase, ForwardDiff using Combinatorics: combinations using PrettyTables: pretty_table, ft_printf using ProgressMeter: @showprogress +using Gadfly: plot, style, Guide, Geom, pt, vstack, hstack import Base: show, getindex, length import StatsBase: aic, aicc, bic, coef, coefnames, coeftable, deviance, dof, @@ -22,7 +23,7 @@ export occu, nmix export detection, occupancy, abundance #Utility functions -export allsub +export allsub, whiskerplot, effectsplot include("utils.jl") include("links.jl") @@ -34,5 +35,6 @@ include("gof.jl") include("predict.jl") include("occupancy.jl") include("nmix.jl") +include("plots.jl") end diff --git a/src/plots.jl b/src/plots.jl new file mode 100644 index 0000000..2f6268c --- /dev/null +++ b/src/plots.jl @@ -0,0 +1,101 @@ +#Dot and whisker plots of coefficient values + confidence intervals + +#For submodels +""" + whiskerplot(m::UnmarkedSubmodel; level::Real = 0.95) + +Generate a dot-and-whisker plot for all parameters in a given submodel `m`. +Error bars are drawn for given confidence `level`. +""" +function whiskerplot(m::UnmarkedSubmodel; level::Real = 0.95) + + #Build data frame of coefficients and upper/lower bounds + df = DataFrame(names=coefnames(m), coef=coef(m), + se=stderror(m)) + zval = -quantile(Normal(), (1-level)/2) + df[!,:lower] = df.coef - zval * df.se + df[!,:upper] = df.coef + zval * df.se + + plot(df, x=:names, y=:coef, ymin=:lower, ymax=:upper, + yintercept=[0.0], + style(major_label_font_size=18pt, + minor_label_font_size=16pt, + point_size=5pt,line_width=2pt), + Guide.xlabel("Parameter"), Guide.ylabel("Value"), + Guide.title(string(m.name)), + Geom.point, Geom.errorbar, + Geom.hline(color="orange",style=:dash)) + +end + +#For complete model +""" + whiskerplot(m::UnmarkedModel; level::Real = 0.95) + +Generate a dot-and-whisker plot for all parameters in a given model `m`. +Error bars are drawn for given confidence `level`. +""" +function whiskerplot(m::UnmarkedModel; level::Real = 0.95) + sm = collect(m.submodels) + vstack(whiskerplot.(sm, level=level)) +end + +#------------------------------------------------------------------------------ + +#Partial effects plots for each parameter + +#For a single parameter +""" + effectsplot(m::UnmarkedSubmodel, param::String; level::Real = 0.95) + +Generate a partial effects plot for parameter `param` from submodel `m`. +The response variable is plotted on the original scale. A confidence envelope +is also plotted for the given `level`. +""" +function effectsplot(m::UnmarkedSubmodel, param::String; level::Real = 0.95) + #Build newdata for predict + psym = Symbol(param) + dat = deepcopy(m.data) + param_dat = dat[:, psym] + val_rng = collect(range(min(param_dat...), stop=max(param_dat...), + length=100)) + mns = colwise(mean, dat) + nd = DataFrame() + for i in 1:length(mns) nd[!,names(dat)[i]] = repeat([mns[i]],100) end + nd[!, psym] = val_rng + + #Predict values + pr = DataFrame(predict(m, nd, interval=true, level=level)) + pr[!, psym] = val_rng + + #Plot line with CI ribbon + resp = string(m.formula.lhs.sym) + plot(pr, x=psym, y=:prediction, ymin=:lower, ymax=:upper, + Geom.line, Geom.ribbon, + style(major_label_font_size=18pt, + minor_label_font_size=16pt), + Guide.xlabel(param), Guide.ylabel(resp)) + +end + +#For a submodel +""" + effectsplot(m::UnmarkedSubmodel; level::Real = 0.95) + +Partial effects plot for all parameters in a submodel `m`. +""" +function effectsplot(m::UnmarkedSubmodel; level::Real = 0.95) + vars = string.(names(m.data)) + vstack(map(x -> effectsplot(m, x, level=level), vars)) +end + +#For a complete model +""" + effectsplot(m::UnmarkedModel; level::Real = 0.95) + +Partial effects plot for all parameters in a model `m`. +""" +function effectsplot(m::UnmarkedModel; level::Real = 0.95) + cols = effectsplot.(collect(m.submodels), level=level) + hstack(cols[1], cols[2]) +end |