I have some code (attached) for generating a box plot overlayed with a “jitter” plot (Jittered points — geom_jitter • ggplot2) – that is, each box has a bunch of scatter points that are aligned with it. I am trying to extend this to the case where boxes are grouped (i.e., a groupedboxplot). In order to do so, I need to plot the boxes first with groupedboxplot, then extract their positions so I can correctly position the scatter points. How does one do this? Thanks!
function jitter_vals(values; width=0.05)
return values .+ width .* (rand(length(values)) .- 0.5)
end
function jitter_plot(conditions, plot_conditions,
plot_normalization, normalization_method, plot_title,
plot_ylabel, plot_xlabel,
plot_yticks, plot_xticks,
plot_filename, data, default_color, plot_size, plots_directory, ylims, yscale)
data = [combine(df, names(df) .=> maximum .=> names(df)) for df in data]
if plot_normalization != ""
norm_data = []
for i in eachindex(conditions)
if plot_normalization in keys(conditions[i])
subset = data[i][!, conditions[i][plot_normalization]]
for entry in subset[1, :]
push!(norm_data, entry)
end
end
end
norm_mean = mean(norm_data)
end
categories = String[]
values = Float64[]
cat_labels = String[]
for condition in plot_conditions
for i in eachindex(conditions)
if condition in keys(conditions[i])
for col in conditions[i][condition]
append!(categories, repeat([condition], length(data[i][!, col])))
if normalization_method == "percent"
append!(values, (data[i][!, col] ./ norm_mean .- 1) .* 100)
elseif normalization_method == "fold-change"
append!(values, data[i][!, col] ./ norm_mean)
elseif normalization_method == ""
append!(values, data[i][!, col])
end
append!(cat_labels, repeat([col], length(data[i][!, col])))
end
end
end
end
unique_cats = unique(categories)
cat_indices = Dict(cat => i for (i, cat) in enumerate(unique_cats))
x_vals = [cat_indices[cat] + jitter_vals([0]; width=0.1)[1] for cat in categories]
x_min = minimum(x_vals) - 0.5
x_max = maximum(x_vals) + 0.5
box_x = [cat_indices[cat] for cat in categories]
if occursin("\$", plot_xlabel)
plot_xlabel = convert_latex(plot_xlabel)
end
if occursin("\$", plot_ylabel[1])
plot_ylabel[1] = convert_latex(plot_ylabel[1])
end
if occursin("\$", plot_title)
plot_title = convert_latex(plot_title)
end
for (k,e) in enumerate(unique_cats)
if occursin("\$", e)
unique_cats[k] = convert_latex(e)
end
end
if yscale == "linear"
yscale = :identity
elseif yscale == "log"
yscale = :log10
end
if ylims == "default"
p = scatter(x_vals, values, group=categories, color=default_color,
markerstrokecolor=default_color, alpha=0.4,
xrotation=45, yscale=yscale,
xlims=(x_min, x_max), size=plot_size)
boxplot!(p, box_x, values, color=default_color, yscale=yscale, linecolor=default_color,
markerstrokecolor=default_color, leg=false, outliers=false,
fillalpha=0.1, linewidth=1.5)
else
for (k, e) in enumerate(ylims)
if e == "nothing"
if k == 1
ylims[k] = -Inf
else
ylims[k] = Inf
end
end
end
ylims = Tuple(ylims)
p = scatter(x_vals, values, group=categories, color=default_color,
markerstrokecolor=default_color, yscale=yscale, alpha=0.4,
xrotation=45,
xlims=(x_min, x_max), ylims=ylims, size=plot_size)
boxplot!(p, box_x, values, color=default_color, yscale=yscale, linecolor=default_color,
markerstrokecolor=default_color, leg=false, outliers=false,
fillalpha=0.1, linewidth=1.5)
end
if plot_xlabel == ""
xticks!(1:length(unique_cats), unique_cats)
else
xticks!(1:length(unique_cats), string.(plot_xticks))
end
xlabel!(p, plot_xlabel)
ylabel!(p, plot_ylabel[1])
title!(p, plot_title)
savefig(p, "$plots_directory/$plot_filename"*".svg")
end