Implement geom_beeswarm using a quasi-random algorithm - #1068
Conversation
|
Just checking if this feature is of interest? |
Yes. I will get to it before the next minor release v0.16.0. |
has2k1
left a comment
There was a problem hiding this comment.
I could also refactor the PR, so that
stat_sinaandstat_beeswarmuse a common code base.
They do have a lot of code in common and it would be make sense if the refactor can extract some meaningful structure beyond the stat methods. Otherwise we can leave it as it is.
|
Hey, I don't think I will get around to making the changes this week. If you would like to include the feature in the upcoming release, feel free to make any edits necessary. Otherwise, I hope to have some more free time for this in September :) |
The method uses the van der Corput algorithm to produce a low discrepancy sequence between 0 and 1.
Add `random_state` to `stat_beeswarm` and use it when integer `y` values need jittering. This replaces the fixed seed and matches `stat_sina`'s random-state interface. Reduce the test's univariate chi-square degrees of freedom from 17 to 3 so all three distributions occupy comparable portions of the panel.
Move density estimation, width scaling, point offsets, and style mirroring into a shared swarm module. Keep each stat's distinct offset strategy and sparse-group density while removing the duplicated layout pipeline. Resolve `random_state` once during parameter setup. A seeded `stat_sina` layer therefore advances one random stream across its offset and jitter draws.
Pass the resolved stat parameters into the uniform-offset calculation and read `random_state` there. Both the offset calculation and integer `y` jitter now consume the same resolved random stream.
Multiply the pandas width fractions before the NumPy random values so the uniform-offset calculation retains the input index and returns a Series.
Rename the uniform and van der Corput offset calculations to `pseudorandom` and `quasirandom`. These names match the public spread strategies and prepare the calculations for shared dispatch.
Add `smiley` and `frowney` offset calculations. Both divide each group into `y` neighbourhoods and alternate ranked values across the swarm; `smiley` places extreme values near the edges, while `frowney` places them near the centre.
Map each spread name to its offset calculation and reject unknown values. This gives the beeswarm stat one entry point for selecting quasirandom, pseudorandom, smiley, or frowney placement.
Add the `spread` parameter to `stat_beeswarm` and `geom_beeswarm`. Users can select quasirandom, pseudorandom, smiley, or frowney point placement; quasirandom remains the default. Add visual coverage for the smiley and frowney strategies.
Mark the wrapped `spread` signature as a continued line so numpydoc parses its choices and default as one parameter declaration.
Add `geom_beeswarm` and `stat_beeswarm` to the API reference and describe their swarm placement in the changelog and class docs. Document the shared offset calculations, clarify how `random_state` affects pseudorandom placement, and list valid spread values in errors. Add pseudorandom visual coverage and align test names with their assertions.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1068 +/- ##
==========================================
+ Coverage 88.05% 88.09% +0.03%
==========================================
Files 223 226 +3
Lines 16440 16550 +110
Branches 2108 2116 +8
==========================================
+ Hits 14477 14580 +103
- Misses 1352 1357 +5
- Partials 611 613 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@const-ae thanks for initiating this. I refactored it to use a common code base with |
|
Nice, looking forward to using this in the next release. |
Fixes #318.
This PR implements a beeswarm algorithm that produces a (in my opinion) visually more appealing output than the random sampling implemented in geom_sina.
The code and unit testes are mostly copied from [geom|stat]_sina. I removed the
random_stateparameter as it isn't needed anymore (except when jitter is called). I wasn't sure what the best way to do here is, so any feedback would be appreciated.I could also refactor the PR, so that stat_sina and stat_beeswarm use a common code base.