-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes #393 This PR adds the keywords `xdodge` and `ydodge` to `mapping` which, like other hardcoded mappings (`layout`, `row`, `col`, `group`) are not tied to any Makie attributes in particular. Instead, these modify any `AesX` or `AesY` columns, respectively, when they are used. This allows generic dodging of things like scatters or errorbars: ```julia df = ( x = [1, 1, 2, 2], y = 1:4, err = [0.5, 0.4, 0.7, 0.6], group = ["A", "B", "A", "B"], ) data(df) * ( mapping(:x, :y, :err, xdodge = :group, color = :group) * visual(Errorbars) + mapping(:x, :y, xdodge = :group, color = :group) * visual(Scatter) ) |> draw(scales(DodgeX = (; width = 0.2))) ``` <img width="442" alt="image" src="https://github.com/user-attachments/assets/1cbef74d-2f9c-477e-9dfa-163d4b256b8b"> The width of the dodging can be controlled with a scale attribute: ```julia mapping( repeat(string.('A' .+ (0:9)), inner = 20), randn(200), xdodge = repeat(["X", "Y"], 100), strokecolor = repeat(["X", "Y"], 100), ) * visual(Scatter, strokewidth = 2, color = :transparent) |> draw(scales(DodgeX = (; width = 0.5))) ``` <img width="536" alt="image" src="https://github.com/user-attachments/assets/8285fb43-75aa-4285-a79d-4e835ab2d9ba"> # Caveats / remaining design problems The most common scenario is errorbars on barplots, I think. However, barplots implement their own dodging via the `dodge` keyword. (There are a couple recipes that have `dodge` implemented, rainclouds, crossbars, violins...) And the width does not depend on the dodging scale but on the plot's own `width` setting as well as `gap` and `dodge_gap`. So one can have mismatched dodging: ```julia df = ( x = [1, 1, 2, 2], y = 1:4, err = [0.5, 0.4, 0.7, 0.6], group = ["A", "B", "A", "B"], ) data(df) * ( mapping(:x, :y, dodge = :group, color = :group) * visual(BarPlot) + mapping(:x, :y, :err, xdodge = :group) * visual(Errorbars) ) |> draw(scales(DodgeX = (; width = 0.2))) ``` <img width="539" alt="image" src="https://github.com/user-attachments/assets/fbd3930f-6c12-43e4-a82f-84a232e71ab9"> One could use `xdodge` for barplot as well, but then this can conflict with the `width` setting from barplot, which would then not be adjusted for anymore (barplot wouldn't know that dodging is going on) ```julia df = ( x = [1, 1, 2, 2], y = 1:4, err = [0.5, 0.4, 0.7, 0.6], group = ["A", "B", "A", "B"], ) data(df) * ( mapping(:x, :y, xdodge = :group, color = :group) * visual(BarPlot, width = 1) + mapping(:x, :y, :err, xdodge = :group) * visual(Errorbars) ) |> draw(scales(DodgeX = (; width = 0.2))) ``` <img width="544" alt="image" src="https://github.com/user-attachments/assets/f3687dd3-5a37-4351-845d-28f4f3dd307d"> Note that in this particular case, if `width = 1` wasn't set, the plot would look ok, but that might not always be the case if enough categories are missing, so it's too brittle I think. <img width="542" alt="image" src="https://github.com/user-attachments/assets/99f27dbd-6b25-4c42-975d-213c910c8bd6"> So ideally, I think the `width` for widthless plots (scatter, errorbars, etc.) could be inferred from plots with width that are also using the dodge scale. So if a barplot is in the mix, the width would be picked up from it somehow. This adds a small layer of complexity on top of the processing pipeline but might be manageable.
- Loading branch information
1 parent
7e316ba
commit 2ab0756
Showing
14 changed files
with
356 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
{ | ||
"description": "Some advanced keywords to tweak the plot", | ||
"order": ["discrete_scales.jl", "continuous_scales.jl", "custom_scales.jl", "secondary_scales.jl", "multiple_color_scales.jl", "prescaled_data.jl", "legend_merging.jl"] | ||
"order": ["discrete_scales.jl", "continuous_scales.jl", "custom_scales.jl", "secondary_scales.jl", "multiple_color_scales.jl", "prescaled_data.jl", "legend_merging.jl", "dodging.jl"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# --- | ||
# title: Dodging | ||
# cover: assets/dodging.png | ||
# description: Dodging groups to avoid overlaps. | ||
# author: "Julius Krumbiegel" | ||
# id: dodging | ||
# --- | ||
|
||
using AlgebraOfGraphics, CairoMakie | ||
using Colors | ||
set_aog_theme!() #src | ||
|
||
# Some plot types like barplots natively support a `dodge` attribute which avoids overlap between | ||
# groups that share the same coordinates. | ||
|
||
df = (; x = ["One", "One", "Two", "Two"], y = 1:4, err = [0.2, 0.3, 0.4, 0.5], group = ["A", "B", "A", "B"]) | ||
plt = data(df) * mapping(:x, :y, dodge = :group, color = :group) * visual(BarPlot) | ||
draw(plt) | ||
|
||
# Other plot types like errorbars do not have a `dodge` keyword, however you can dodge them using | ||
# AlgebraOfGraphic's hardcoded `dodge_x` or `dodge_y` mappings. | ||
# These will only shift the data away from the category centers but will not change | ||
# other plot attributes (like dodging a barplot makes narrower bars). | ||
# They are therefore mostly appropriate for "width-less" plot types like scatters or errorbars. | ||
# | ||
# If you combine errorbars with a barplot, AlgebraOfGraphics will apply the barplot's dodge width | ||
# to the errorbars automatically so they match: | ||
|
||
plt2 = data(df) * mapping(:x, :y, :err, dodge_x = :group) * visual(Errorbars) | ||
fg = draw(plt + plt2) | ||
|
||
# If you only use "width-less" plot types, you will get an error if you don't set a dodge width manually. | ||
# You can do so via the `scales` function: | ||
|
||
df = ( | ||
x = repeat(1:10, inner = 2), | ||
y = cos.(range(0, 2pi, length = 20)), | ||
ylow = cos.(range(0, 2pi, length = 20)) .- 0.2, | ||
yhigh = cos.(range(0, 2pi, length = 20)) .+ 0.3, | ||
dodge = repeat(["A", "B"], 10) | ||
) | ||
|
||
f = Figure() | ||
plt3 = data(df) * ( | ||
mapping(:x, :y, dodge_x = :dodge, color = :dodge) * visual(Scatter) + | ||
mapping(:x, :ylow, :yhigh, dodge_x = :dodge, color = :dodge) * visual(Rangebars) | ||
) | ||
kw(; kwargs...) = (; xticklabelsvisible = false, xticksvisible = false, xlabelvisible = false, kwargs...) | ||
|
||
draw!(f[1, 1], plt3, scales(DodgeX = (; width = 0.25)); axis = kw(title = "DodgeX = (; width = 0.25)")) | ||
draw!(f[2, 1], plt3, scales(DodgeX = (; width = 0.5)); axis = kw(title = "DodgeX = (; width = 0.5)")) | ||
draw!(f[3, 1], plt3, scales(DodgeX = (; width = 1.0)); axis = (; title = "DodgeX = (; width = 1.0)")) | ||
|
||
f | ||
|
||
# save cover image #src | ||
mkpath("assets") #src | ||
save("assets/dodging.png", fg) #src |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.