raphaelvallat / pingouin

Statistical package in Python based on Pandas
https://pingouin-stats.org/
GNU General Public License v3.0
1.61k stars 138 forks source link

Fix boxplot z-order in `plot_paired` #442

Closed sbwiecko closed 2 days ago

sbwiecko commented 6 days ago

Description:

This pull request addresses two issues in the plot_paired function related to the boxplot_in_front parameter:

  1. Incorrect behavior when boxplot_in_front=False: the boxplot was being drawn above the lines and markers even when this parameter was set to False, contradicting its intended functionality.
  2. Boxplot disappearance when boxplot_in_front=False after initial fix: an earlier attempt to fix the first issue resulted in the boxplot disappearing completely because its z-order was set too low.
Python 3.12.6
-------------
numpy: 1.26.4
pandas: 2.2.2
matplotlib: 3.9.2
seaborn: 0.13.2
pingouin: 0.5.5

Root Cause:

Solution:

The fix involves:

  1. Introducing explicit z-order control for the boxplot elements in both branches of the conditional statement.
  2. Setting appropriate z-orders to ensure correct layering:
    • When boxplot_in_front=True, the boxplot has a z-order of 3 (on top).
    • When boxplot_in_front=False, the boxplot has a z-order of 1 (behind).
    • The lines and markers maintain their default z-order of 2.

Impact:

This change ensures that the boxplot_in_front parameter functions correctly and consistently, providing users with accurate control over the visual layering of plot elements in plot_paired.

Testing:

Thorough testing has been conducted with various combinations of boxplot_in_front and other plot settings to confirm the desired behavior and absence of any regressions. You can use the snippet below for testings.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pingouin as pg

cross_fert = pd.Series([23.5, 12, 21, 22, 19.125, 21.5, 22.125, 20.375, 18.250, 21.625, 23.250, 21, 22.125, 23, 12])
self_fert = pd.Series([17.375, 20.375, 20, 20, 18.375, 18.625, 18.625, 15.25, 16.5, 18, 16.25, 18, 12.75, 15.5, 18])

data_fert = pd.concat(
    [cross_fert, self_fert],
    keys=['cross_fert', 'self_fert'],
    axis=1)

pg.plot_paired(
    dv='plant_height',
    data=data_fert.reset_index().melt(
        value_vars=['cross_fert', 'self_fert'],
        id_vars='index',
        var_name='fertilization',
        value_name='plant_height'),
    within='fertilization',
    subject='index',
    boxplot=True,
    orient='v',
    boxplot_in_front=False,
    #boxplot_in_front=True,
    boxplot_kwargs={'color': 'white', 'linewidth': 2},
)

plt.show()

Please review and merge if you find this fix suitable.

Merci Raphael ;-)