Skip to content

Commit

Permalink
Make box/violin legend data more robust
Browse files Browse the repository at this point in the history
This addresses #435.
  • Loading branch information
mwaskom committed Mar 13, 2015
1 parent 268d209 commit 70e7a8f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 16 deletions.
42 changes: 26 additions & 16 deletions seaborn/categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,13 +392,13 @@ def annotate_axes(self, ax):
prop = mpl.font_manager.FontProperties(size=title_size)
leg._legend_title_box._text.set_font_properties(prop)

def add_legend_data(self, ax, x, y, color, label):
def add_legend_data(self, ax, color, label):
"""Add a dummy patch object so we can get legend data."""
rect = plt.Rectangle([x, y], 0, 0,
rect = plt.Rectangle([0, 0], 0, 0,
linewidth=self.linewidth / 2,
edgecolor=self.gray,
facecolor=color,
label=label, zorder=-1)
label=label)
ax.add_patch(rect)


Expand All @@ -424,10 +424,12 @@ def draw_boxplot(self, ax, kws):

for i, group_data in enumerate(self.plot_data):

if not group_data.size:
continue

if self.plot_hues is None:

# Handle case where there is no data to plot
if not group_data.size:
continue

# Draw a single box or a set of boxes
# with a single level of grouping
box_data = remove_na(group_data)
Expand All @@ -444,8 +446,15 @@ def draw_boxplot(self, ax, kws):
offsets = self.hue_offsets
for j, hue_level in enumerate(self.hue_names):
hue_mask = self.plot_hues[i] == hue_level
if not hue_mask.any():

# Add a legend for this hue level
if not i:
self.add_legend_data(ax, self.colors[j], hue_level)

# Handle case where there is no data to plot
if not group_data.size or not hue_mask.any():
continue

box_data = remove_na(group_data[hue_mask])
center = i + offsets[j]
artist_dict = ax.boxplot(box_data,
Expand All @@ -454,13 +463,8 @@ def draw_boxplot(self, ax, kws):
positions=[center],
widths=self.nested_width,
**kws)
color = self.colors[j]
self.restyle_boxplot(artist_dict, color)
self.restyle_boxplot(artist_dict, self.colors[j])
# Add legend data, but just for one set of boxes
if not i:
self.add_legend_data(ax, center,
np.median(box_data),
color, hue_level)

def restyle_boxplot(self, artist_dict, color):
"""Take a drawn matplotlib boxplot and make it look nice."""
Expand Down Expand Up @@ -575,6 +579,14 @@ def estimate_densities(self, bw, cut, scale, scale_hue, gridsize):
else:
for j, hue_level in enumerate(self.hue_names):

# Handle special case of no data at this category level
if not group_data.size:
support[i].append(np.array([]))
density[i].append(np.array([1.]))
counts[i, j] = 0
max_density[i, j] = 0
continue

# Select out the observations for this hue level
hue_mask = self.plot_hues[i] == hue_level

Expand Down Expand Up @@ -788,9 +800,7 @@ def draw_violins(self, ax):

# Add legend data, but just for one set of violins
if not i:
self.add_legend_data(ax, support[0], 0,
self.colors[j],
hue_level)
self.add_legend_data(ax, self.colors[j], hue_level)

# Handle the special case where we have no observations
if support.size == 0:
Expand Down
34 changes: 34 additions & 0 deletions seaborn/tests/test_categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,34 @@ def test_draw_missing_boxes(self):
nt.assert_equal(len(ax.artists), 3)
plt.close("all")

def test_boxplots(self):

# Smoke test the high level boxplot options

cat.boxplot("y", data=self.df)
plt.close("all")

cat.boxplot(y="y", data=self.df)
plt.close("all")

cat.boxplot("g", "y", data=self.df)
plt.close("all")

cat.boxplot("y", "g", data=self.df, orient="h")
plt.close("all")

cat.boxplot("g", "y", "h", data=self.df)
plt.close("all")

cat.boxplot("g", "y", "h", order=list("nabc"), data=self.df)
plt.close("all")

cat.boxplot("g", "y", "h", hue_order=list("omn"), data=self.df)
plt.close("all")

cat.boxplot("y", "g", "h", data=self.df, orient="h")
plt.close("all")

def test_axes_annotation(self):

ax = cat.boxplot("g", "y", data=self.df)
Expand Down Expand Up @@ -1329,6 +1357,12 @@ def test_violinplots(self):
cat.violinplot("g", "y", "h", data=self.df)
plt.close("all")

cat.violinplot("g", "y", "h", order=list("nabc"), data=self.df)
plt.close("all")

cat.violinplot("g", "y", "h", hue_order=list("omn"), data=self.df)
plt.close("all")

cat.violinplot("y", "g", "h", data=self.df, orient="h")
plt.close("all")

Expand Down

0 comments on commit 70e7a8f

Please sign in to comment.