Major update: Seaborn 0.13.2 compatibility and modernized infrastructure (v0.2.7 → v0.3.1)#55
Merged
pog87 merged 7 commits intopog87:masterfrom Oct 6, 2025
Conversation
Seaborn v0.12 and v0.13 introduced significant breaking changes to the internal categorical plotting API, removing `_CategoricalScatterPlotter` and redesigning `_CategoricalPlotter`. This commit refactors the library to restore compatibility with modern Seaborn versions. Key changes include: - **Refactored `_Half_ViolinPlotter`**: - Now inherits from the modern `seaborn._CategoricalPlotter`. - Replaces manual data looping with a more robust and efficient `pandas.groupby` workflow for density estimation. - Modernizes internal data handling to use an intermediate list of dictionaries (`violin_data`) instead of parallel lists for support, density, and counts. - **Rewrote `stripplot` Wrapper**: - The custom `_StripPlotter` class, which depended on the removed API, has been deleted. - The public `stripplot` function is now a lightweight wrapper around the official `sns.stripplot`. - The custom `move` parameter functionality is preserved by manually transforming the plot artist's offsets after it has been drawn. - **Updated Dependencies**: - Bumped the `seaborn` requirement from `0.11` to `0.13.2`. - Updated `matplotlib` version constraints in `setup.py` and `requirements.txt`.
This commit introduces several improvements to the codebase to enhance maintainability, fix a latent bug, and decouple from private APIs. - **Fix `scale_width` Property Bug**: Converts `scale_width` from a `@property` with side effects into a private method `_scale_width()`. This ensures it is called explicitly and corrects the improper use of properties for state-mutating operations. - **Decouple from Seaborn Internals**: Removes the call to Seaborn's private `_complement_color` function. A local, equivalent utility `_get_complementary_gray` is introduced to ensure long-term API stability. - **Add Type Hinting**: Introduces type hints to the public functions (`stripplot`, `half_violinplot`, `RainCloud`) to improve code clarity, enable static analysis, and enhance IDE support. - **Improve Readability**: Adds comments and clarifies logic in `stripplot` and `RainCloud` regarding artist manipulation (`move`) and legend pruning. A constant (`_LEGACY_GRAY`) is also introduced to replace a magic string.
This commit refactors the plotting logic to ensure that when a `hue` variable is used, the components of the raincloud plot (violin, strip plot, box plot) remain aligned on the categorical axis, preserving the intended raincloud aesthetic.
Previously, using a `hue` would cause seaborn's default "dodging" behavior, separating the violins and creating multiple lines in the pointplot, which is not suitable for a raincloud plot where all elements should share a common axis.
The specific changes are:
* **Violin Positioning:** The `_get_center_pos` method in `_Half_ViolinPlotter` has been simplified to remove hue-based horizontal offsets. All violins within a single category now share the same center position, forming a single "cloud."
* **Point Plot ("Thunder Line"):** The call to `sns.pointplot` within the `RainCloud` function no longer passes the `hue` parameter. This ensures that a single line is drawn to connect the means of the main categories, rather than separate, dodged lines for each hue level.
* **Legend Handling:** The old, manual legend creation logic has been removed from `draw_violins`. The plot now uses seaborn's internal `_configure_legend` API within the main `plot` method. This is a more robust and modern approach that aligns with the recent refactoring to support newer seaborn versions.
* **Cloud Direction:** The `split` parameter in `half_violinplot` is no longer toggled when a `hue` is present. This keeps all "clouds" facing the same direction, maintaining the consistent look of the plot.
Seaborn 0.13 emits multiple PathCollections for each stripplot, so the previous assumption that the final collection held all raindrops caused the move parameter to shift only one hue/category. That left some bands centered while others slid to the side. Capture the collection count before calling sns.stripplot and adjust the offsets on every new PathCollection, skipping any without offsets. The rain layer now shifts uniformly for every hue/dodge configuration.
This commit addresses several issues discovered during testing: **Dodge alignment with stripplot:** - Fix stripplot dodge offset to match boxplot width when dodge=True - Seaborn's stripplot uses width=0.8 internally, but RainCloud uses width=0.15 for boxplots, causing misalignment - Implement dodge rescaling by separating dodge offset from jitter using median offset per collection, then scaling only the dodge component while preserving original jitter magnitude **Pointplot with multiple hue levels:** - Fix pointplot to show separate colored lines per hue level when hue represents subgroups (e.g., timepoints) - Previously showed single red line regardless of hue - Now passes hue, palette, and hue_order to sns.pointplot when needed **Axis labels:** - Fix axis labels to use original variable names before x/y swap - Horizontal plots now correctly show categorical var on y-axis and numeric var on x-axis - Vertical plots show categorical var on x-axis and numeric on y-axis **Additional fixes:** - Fix pandas Series comparison bug when determining if hue represents subgroups vs just coloring categories - Improve legend logic to only display when hue is semantically different from categorical variable Version bumped to 0.3.0 to reflect these important behavioral fixes.
the library as of today.
- Migrate from setup.py to modern pyproject.toml with hatchling - Add comprehensive pytest test suite (60 tests, 89% coverage) - Update CI to test Python 3.9-3.12 on Ubuntu - Add pre-commit hooks with ruff for code quality - Remove default palette parameter to avoid seaborn 0.14 warnings - Update type hints to use modern syntax (list/dict instead of List/Dict) - Remove deprecated Python 2 imports - Add CHANGELOG.md and update README with version history - Clean up unused variables and improve code quality
Owner
|
Cool, thank you! Allow me some time to carefully review before merging. |
Owner
|
Approved! Thanks for your valuable contribution. |
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR brings PtitPrince from v0.2.7 to v0.3.1. It includes comprehensive updates for Seaborn 0.13.2 compatibility, along with modernized packaging and testing infrastructure.
Seaborn 0.13.2 Compatibility (v0.3.0)
Core Refactoring
_CategoricalScatterPlotterto modern_CategoricalPlotterbase classorient='x'/'y'instead of'v'/'h'internally)_get_patch_legend_artistBug Fixes
Enhancements
_LEGACY_GRAYconstant for backward-compatible gray color handlingModernized Infrastructure (v0.3.1)
Packaging
pyproject.tomlwith Hatchling build backend (PEP 621 compliant)setup.pyandrequirements.txtdev,notebooksTesting
RainCloud,half_violinplot,stripplotCode Quality
list/dictinstead ofList/Dict)from __future__ import divisionBreaking Changes
palette="Set2"fromRainCloud()to avoid seaborn 0.14 warningspalette='Set2'Documentation
CHANGELOG.mdfollowing Keep a Changelog formatsetup.pyinstallation instructionsUpdated Examples
Testing
python -m buildVersion History
This PR combines work from two releases: