Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inner='box' in violinplot shows too large quartiles and whiskers #3790

Open
higher-bridge opened this issue Nov 26, 2024 · 0 comments
Open

Comments

@higher-bridge
Copy link

When making violinplots, passing inner='box' uses mpl's Axes.plot() to draw the inner boxplot.
However, the default in mpl is solid_capstyle='projecting', which extends the line too far out, and thus exaggerates both the boxplot's quartiles and the whiskers.
This becomes increasingly exaggerated with a larger linewidth, because 'projecting' uses linewidth/2 (https://matplotlib.org/stable/api/_enums_api.html#matplotlib._enums.CapStyle).

Showing incorrect data ranges may be problematic for e.g., scientific publications.
For more accurate plotting, I therefore suggest that seaborn sets the default for inner_kws to solid_capstyle='butt'. This limits the line to its actual endpoints.

I don't know whether this issue may extend to other types of plots as well.

Below is a minimal example which shows both the default and desired behaviours. I am using seaborn 0.13.2.
I set box_width to 12 to make it a bit more obvious, but even at default box_width it happens.

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

# List of 0-100
y = np.linspace(0, 100, 100)
avg, q1, q3 = np.mean(y), np.quantile(y, 1/4), np.quantile(y, 3/4)

# To dataframe
df = pd.DataFrame({'y': y})

# Plot default behaviour
plt.figure()
sns.violinplot(data=df, y='y', cut=0, fill=False, inner='box', inner_kws={'box_width': 12})
plt.axhline(avg, c='black', zorder=-100)
plt.axhline(q1, c='black', zorder=-100)
plt.axhline(q3, c='black', zorder=-100)
plt.yticks([q1, avg, q3], ['q1', 'avg', 'q3'])
plt.title('Default behaviour')
plt.show()

# Plot desired behaviour (inner_kws={'solid_capstyle': 'butt'})
plt.figure()
sns.violinplot(data=df, y='y', cut=0, fill=False, inner='box', inner_kws={'box_width': 12, 'solid_capstyle': 'butt'})
plt.axhline(avg, c='black', zorder=-100)
plt.axhline(q1, c='black', zorder=-100)
plt.axhline(q3, c='black', zorder=-100)
plt.yticks([q1, avg, q3], ['q1', 'avg', 'q3'])
plt.title('Desired behaviour (solid_capstyle = "butt")')
plt.show()

image
image

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

No branches or pull requests

1 participant