Skip to content

Plotting improvements#513

Open
raphaelvallat wants to merge 6 commits into
mainfrom
plot_improvements
Open

Plotting improvements#513
raphaelvallat wants to merge 6 commits into
mainfrom
plot_improvements

Conversation

@raphaelvallat
Copy link
Copy Markdown
Owner

This PR improves all plotting functions in pingouin/plotting.py. Changes span bug fixes, new
parameters, API corrections, and code clarity improvements.


Bug fixes

plot_paired: ax.artists replaced with ax.patches

The boxplot transparency logic used ax.artists, which was removed in recent versions of
matplotlib. This caused an AttributeError at runtime whenever boxplot=True (the default). It
is now replaced with the correct ax.patches.

qqplot: normalization condition corrected

The condition that normalizes observed quantiles read:

if loc != 0 and scale != 1:

This meant normalization was skipped whenever only one of loc or scale differed from the
identity transform (for example, a fit with loc=0 but scale=2.5). The condition is now:

if loc != 0 or scale != 1:

Mutable default arguments fixed in plot_paired, plot_rm_corr, plot_circmean

All three functions used mutable objects (list or dict) as default parameter values. This is a
known Python pitfall: if a caller mutated the default object, all subsequent calls would be
affected. The defaults are now None and the internal defaults are constructed fresh on each call.

Affected parameters:

Function Parameters
plot_paired colors, pointplot_kwargs, boxplot_kwargs
plot_rm_corr kwargs_facetgrid, kwargs_line, kwargs_scatter
plot_circmean kwargs_markers, kwargs_arrow

The default values are unchanged. Existing call sites that pass these arguments explicitly are
unaffected.


New functionality

plot_blandaltman: percentage parameter

ax = pg.plot_blandaltman(df["A"], df["B"], percentage=True)

When percentage=True, differences are expressed as (x - y) / mean(x, y) * 100. This is the
recommended form of the Bland-Altman plot when measurement variability scales with magnitude or
when the two methods use different units/ranges. The y-axis label is updated to include [%].

qqplot: line_kwargs and ci_kwargs parameters

The regression fit line and confidence envelope were previously hardcoded as red ("r-" and
"r--"). Two new optional parameters allow full control over their appearance:

ax = pg.qqplot(
    x,
    line_kwargs={"color": "steelblue", "lw": 1.5},
    ci_kwargs={"color": "steelblue", "ls": ":", "lw": 1},
)

Both parameters accept any keyword arguments accepted by matplotlib.pyplot.plot. Omitting them
reproduces the previous default style.


Visual improvements to plot_blandaltman

Zero reference line

A light grey horizontal line is drawn at y = 0 (perfect agreement) behind all other plot
elements. This is a standard component of Bland-Altman plots that was previously missing.

Symmetric y-axis

The y-axis is now forced to be symmetric around zero. This prevents visual bias when the mean
difference is close to zero but the axis happens to be asymmetric due to the data range.

Corrected annotation labels

The upper and lower limits of agreement (LoA) labels previously read "+1.96 SD", which is only
accurate when agreement=1.96. The labels now read +{agreement:.2f}×SD and
−{agreement:.2f}×SD and are accurate for any value of agreement.

Decoupled CI band colors

The confidence interval bands for the limits of agreement previously inherited the scatter point
color. This meant that setting color="tab:red" would also change the LoA CI bands to red. The
colors are now independent:

  • Bias (mean difference) CI band: tab:gray
  • LoA CI bands: tab:blue

Limits of agreement line style

The LoA lines are now drawn with linestyle="--" (dashed) instead of linestyle=":" (dotted),
which is the more common convention and improves legibility at small figure sizes.


Code clarity

plot_circmean: simplified default-merging

The 10-line block of if "key" not in dict checks has been replaced with a single dict merge:

_kwargs_markers = {"color": "tab:blue", "marker": "o", "mfc": "none", "ms": 10, **(kwargs_markers or {})}
_kwargs_arrow = {"width": 0.01, "head_width": 0.1, "head_length": 0.1, "fc": "tab:red", "ec": "tab:red", **(kwargs_arrow or {})}

_ppoints: added formula comment

A short comment now links the a constant to Blom (1958), the original source for the two values
(3/8 for small samples, 0.5 otherwise).

plot_blandaltman: SE formula comment

A comment on the LoA standard error formula now cites the original Bland and Altman (1986) paper,
making the non-obvious sqrt(3 * s² / n) expression self-documenting.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.70%. Comparing base (2d906c5) to head (f1be82b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #513      +/-   ##
==========================================
+ Coverage   98.36%   98.70%   +0.33%     
==========================================
  Files          19       19              
  Lines        3305     3313       +8     
  Branches      488      485       -3     
==========================================
+ Hits         3251     3270      +19     
+ Misses         32       28       -4     
+ Partials       22       15       -7     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes and extends Pingouin’s plotting utilities in src/pingouin/plotting.py, addressing compatibility issues with newer matplotlib versions, improving statistical correctness, and adding small API extensions for customization.

Changes:

  • Fix plotting runtime issues and correctness bugs (e.g., plot_paired boxplot alpha handling, qqplot normalization condition).
  • Add new plotting options (plot_blandaltman(percentage=...), qqplot(line_kwargs=..., ci_kwargs=...)) and improve Bland–Altman visuals.
  • Remove mutable default arguments across plotting functions and add targeted test coverage for new/changed branches.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
src/pingouin/plotting.py Implements plotting fixes, new parameters, improved annotations/styling, and safer default handling.
tests/test_plotting.py Extends tests to cover new parameters and additional execution branches / error paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/pingouin/plotting.py
Comment thread src/pingouin/plotting.py
Comment thread src/pingouin/plotting.py Outdated
Comment thread src/pingouin/plotting.py
Comment thread src/pingouin/plotting.py
Comment thread src/pingouin/plotting.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants