Skip to content

Commit 548b854

Browse files
authored
Set alpha properly on unfilled hist/kde plots (#2460)
* Set alpha properly on unfilled hist/kde plots Fixes #2450 * Fix typo in kdeplot docstring * Generalize color comparison
1 parent 136b462 commit 548b854

File tree

6 files changed

+101
-75
lines changed

6 files changed

+101
-75
lines changed

doc/releases/v0.12.0.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ v0.12.0 (Unreleased)
2020

2121
- |Fix| In :func:`rugplot`, fixed a bug that prevented the use of datetime data (:pr:`2458`).
2222

23+
- |Fix| In :func:`histplot` and :func:`kdeplot`, fixed a bug where the `alpha` parameter was ignored when `fill=False` (:pr:`2460`).
24+
2325
- |Fix| |Enhancement| Improved integration with the matplotlib color cycle in most axes-level functions (:pr:`2449`).
2426

2527
- Made `scipy` an optional dependency and added `pip install seaborn[all]` as a method for ensuring the availability of compatible `scipy` and `statsmodels` libraries at install time. This has a few minor implications for existing code, which are explained in the Github pull request (:pr:`2398`).

seaborn/_statistics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def __init__(
6565
Factor, multiplied by the smoothing bandwidth, that determines how
6666
far the evaluation grid extends past the extreme datapoints. When
6767
set to 0, truncate the curve at the data limits.
68-
clip : pair of numbers None, or a pair of such pairs
68+
clip : pair of numbers or None, or a pair of such pairs
6969
Do not evaluate the density outside of these limits.
7070
cumulative : bool, optional
7171
If True, estimate a cumulative distribution function. Requires scipy.

seaborn/_testing.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import numpy as np
22
import matplotlib as mpl
3+
from matplotlib.colors import to_rgb, to_rgba
34
from numpy.testing import assert_array_equal
45

56

@@ -69,3 +70,21 @@ def assert_plots_equal(ax1, ax2, labels=True):
6970
if labels:
7071
assert ax1.get_xlabel() == ax2.get_xlabel()
7172
assert ax1.get_ylabel() == ax2.get_ylabel()
73+
74+
75+
def assert_colors_equal(a, b, check_alpha=True):
76+
77+
def handle_array(x):
78+
79+
if isinstance(x, np.ndarray):
80+
if x.ndim > 1:
81+
x = np.unique(x, axis=0).squeeze()
82+
if x.ndim > 1:
83+
raise ValueError("Color arrays must be 1 dimensional")
84+
return x
85+
86+
a = handle_array(a)
87+
b = handle_array(b)
88+
89+
f = to_rgba if check_alpha else to_rgb
90+
assert f(a) == f(b)

seaborn/distributions.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,9 @@ def _artist_kws(self, kws, fill, element, multiple, color, alpha):
185185
kws.setdefault("edgecolor", to_rgba(color, 1))
186186
elif element == "bars":
187187
kws["facecolor"] = "none"
188-
kws["edgecolor"] = to_rgba(color, 1)
188+
kws["edgecolor"] = to_rgba(color, alpha)
189189
else:
190-
kws["color"] = color
190+
kws["color"] = to_rgba(color, alpha)
191191
return kws
192192

193193
def _quantile_to_level(self, data, quantile):
@@ -502,12 +502,15 @@ def plot_univariate_histogram(
502502
# Note: default linewidth is determined after plotting
503503

504504
# Default alpha should depend on other parameters
505-
if multiple == "layer":
506-
default_alpha = .5 if element == "bars" else .25
507-
elif kde:
508-
default_alpha = .5
505+
if fill:
506+
if multiple == "layer":
507+
default_alpha = .5 if element == "bars" else .25
508+
elif kde:
509+
default_alpha = .5
510+
else:
511+
default_alpha = .75
509512
else:
510-
default_alpha = .75
513+
default_alpha = 1
511514
alpha = plot_kws.pop("alpha", default_alpha) # TODO make parameter?
512515

513516
hist_artists = []
@@ -914,7 +917,10 @@ def plot_univariate_density(
914917
sticky_support = []
915918

916919
# XXX unfilled kdeplot is ignoring
917-
default_alpha = .25 if multiple == "layer" else .75
920+
if fill:
921+
default_alpha = .25 if multiple == "layer" else .75
922+
else:
923+
default_alpha = 1
918924
alpha = plot_kws.pop("alpha", default_alpha) # TODO make parameter?
919925

920926
# Now iterate through the subsets and draw the densities

seaborn/tests/test_axisgrid.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from .. import axisgrid as ag
2121
from .._testing import (
2222
assert_plots_equal,
23+
assert_colors_equal,
2324
)
2425

2526
rs = np.random.RandomState(0)
@@ -224,7 +225,7 @@ def test_legend_data(self):
224225
assert len(lines) == len(a_levels)
225226

226227
for line, hue in zip(lines, palette):
227-
assert line.get_color() == hue
228+
assert_colors_equal(line.get_color(), hue)
228229

229230
labels = g._legend.get_texts()
230231
assert len(labels) == len(a_levels)
@@ -249,7 +250,7 @@ def test_legend_data_missing_level(self):
249250
assert len(lines) == len(a_levels)
250251

251252
for line, hue in zip(lines, palette):
252-
assert line.get_color() == hue
253+
assert_colors_equal(line.get_color(), hue)
253254

254255
labels = g._legend.get_texts()
255256
assert len(labels) == 4
@@ -273,7 +274,7 @@ def test_get_boolean_legend_data(self):
273274
assert len(lines) == len(b_levels)
274275

275276
for line, hue in zip(lines, palette):
276-
assert line.get_color() == hue
277+
assert_colors_equal(line.get_color(), hue)
277278

278279
labels = g._legend.get_texts()
279280
assert len(labels) == len(b_levels)
@@ -941,21 +942,20 @@ def test_map_diag_rectangular(self):
941942
def test_map_diag_color(self):
942943

943944
color = "red"
944-
rgb_color = mpl.colors.colorConverter.to_rgba(color)
945945

946946
g1 = ag.PairGrid(self.df)
947947
g1.map_diag(plt.hist, color=color)
948948

949949
for ax in g1.diag_axes:
950950
for patch in ax.patches:
951-
assert patch.get_facecolor() == rgb_color
951+
assert_colors_equal(patch.get_facecolor(), color)
952952

953953
g2 = ag.PairGrid(self.df)
954954
g2.map_diag(kdeplot, color='red')
955955

956956
for ax in g2.diag_axes:
957957
for line in ax.lines:
958-
assert line.get_color() == color
958+
assert_colors_equal(line.get_color(), color)
959959

960960
def test_map_diag_palette(self):
961961

@@ -966,7 +966,7 @@ def test_map_diag_palette(self):
966966

967967
for ax in g.diag_axes:
968968
for line, color in zip(ax.lines[::-1], pal):
969-
assert line.get_color() == color
969+
assert_colors_equal(line.get_color(), color)
970970

971971
def test_map_diag_and_offdiag(self):
972972

@@ -1656,12 +1656,11 @@ def test_color(self):
16561656

16571657
g = ag.jointplot(x="x", y="y", data=self.data, color="purple")
16581658

1659-
purple = mpl.colors.colorConverter.to_rgb("purple")
1660-
scatter_color = g.ax_joint.collections[0].get_facecolor()[0, :3]
1661-
assert tuple(scatter_color) == purple
1659+
scatter_color = g.ax_joint.collections[0].get_facecolor()
1660+
assert_colors_equal(scatter_color, "purple")
16621661

16631662
hist_color = g.ax_marg_x.patches[0].get_facecolor()[:3]
1664-
assert hist_color == purple
1663+
assert_colors_equal(hist_color, "purple")
16651664

16661665
def test_palette(self, long_df):
16671666

0 commit comments

Comments
 (0)