Skip to content

Commit

Permalink
Merge 4772a6d into 005d4c7
Browse files Browse the repository at this point in the history
  • Loading branch information
maziello committed Feb 7, 2020
2 parents 005d4c7 + 4772a6d commit a4273cd
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 18 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.rst
@@ -1,6 +1,7 @@
In development
--------------

- Added option to display both the absolute frequency and the percentage of
the total for each intersection and category.
- Improved efficiency where there are many categories, but valid combinations
are sparse, if `sort_by='degree'`. (:issue:`82`)
- Permit truthy (not necessarily bool) values in index. (:issue:`74`)
Expand Down
2 changes: 1 addition & 1 deletion upsetplot/__init__.py
@@ -1,4 +1,4 @@
__version__ = '0.4-dev'
__version__ = '0.4.dev1'

import os

Expand Down
70 changes: 54 additions & 16 deletions upsetplot/plotting.py
Expand Up @@ -272,6 +272,8 @@ class UpSet:
Whether to label the intersection size bars with the cardinality
of the intersection. When a string, this formats the number.
For example, '%d' is equivalent to True.
'%' or 'pctg' or 'percentage' displays both the absolute frequency and
the percentage of the total for each intersection and category
sort_sets_by
.. deprecated: 0.3
Replaced by sort_categories_by, this parameter will be removed in
Expand All @@ -285,7 +287,8 @@ def __init__(self, data, orientation='horizontal', sort_by='degree',
facecolor='black',
with_lines=True, element_size=32,
intersection_plot_elements=6, totals_plot_elements=2,
show_counts='', sort_sets_by='deprecated'):
show_counts='', show_percentages=False,
sort_sets_by='deprecated'):

self._horizontal = orientation == 'horizontal'
self._reorient = _identity if self._horizontal else _transpose
Expand All @@ -299,6 +302,7 @@ def __init__(self, data, orientation='horizontal', sort_by='degree',
if not intersection_plot_elements:
self._subset_plots.pop()
self._show_counts = show_counts
self._show_percentages = show_percentages

if sort_sets_by != 'deprecated':
sort_categories_by = sort_sets_by
Expand Down Expand Up @@ -429,7 +433,7 @@ def make_grid(self, fig=None):
self._totals_plot_elements),
hspace=1)
if self._horizontal:
print(n_cats, n_inters, self._totals_plot_elements)
# print(n_cats, n_inters, self._totals_plot_elements)
out = {'matrix': gridspec[-n_cats:, -n_inters:],
'shading': gridspec[-n_cats:, :],
'totals': gridspec[-n_cats:, :self._totals_plot_elements],
Expand All @@ -446,8 +450,8 @@ def make_grid(self, fig=None):
cumsizes = np.cumsum(sizes)
for start, stop, plot in zip(np.hstack([[0], cumsizes]), cumsizes,
self._subset_plots):
out[plot['id']] = gridspec[-n_inters:,
start + n_cats:stop + n_cats]
out[plot['id']] = \
gridspec[-n_inters:, start + n_cats:stop + n_cats]
return out

def plot_matrix(self, ax):
Expand Down Expand Up @@ -505,32 +509,66 @@ def plot_intersections(self, ax):
ax.set_ylabel('Intersection size')

def _label_sizes(self, ax, rects, where):
if not self._show_counts:
if not self._show_counts and not self._show_percentages:
return
fmt = '%d' if self._show_counts is True else self._show_counts
if where == 'right':
margin = 0.01 * abs(np.diff(ax.get_xlim()))
for rect in rects:
width = rect.get_width()
ax.text(width + margin,
rect.get_y() + rect.get_height() * .5,
fmt % width,
ha='left', va='center')
if self._show_percentages:
ax.text(width + margin,
rect.get_y() + rect.get_height() * .5,
fmt % width +
" (%.1f%%)" % (100 * width /
max(1, sum(self.intersections)))
if self._show_counts else
"%.1f%%" % (100 * width /
max(1, sum(self.intersections))),
ha='left', va='center')
else:
ax.text(width + margin,
rect.get_y() + rect.get_height() * .5,
fmt % width,
ha='left', va='center')
elif where == 'left':
margin = 0.01 * abs(np.diff(ax.get_xlim()))
for rect in rects:
width = rect.get_width()
ax.text(width + margin,
rect.get_y() + rect.get_height() * .5,
fmt % width,
ha='right', va='center')
if self._show_percentages:
ax.text(width + margin,
rect.get_y() + rect.get_height() * .5,
fmt % width +
" (%.1f%%)" % (100 * width /
max(1, sum(self.intersections)))
if self._show_counts
else "%.1f%%" % (100 * width /
max(1, sum(self.intersections))),
ha='right', va='center')
else:
ax.text(width + margin,
rect.get_y() + rect.get_height() * .5,
fmt % width,
ha='right', va='center')
elif where == 'top':
margin = 0.01 * abs(np.diff(ax.get_ylim()))
for rect in rects:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width() * .5,
height + margin, fmt % height,
ha='center', va='bottom')
if self._show_percentages:
ax.text(rect.get_x() + rect.get_width() * .5,
height + margin,
fmt % height +
"\n(%.1f%%)" % (100 * height /
max(1, sum(self.intersections)))
if self._show_counts
else "%.1f%%" % (100 * height /
max(1, sum(self.intersections))),
ha='center', va='bottom', fontsize=8)
else:
ax.text(rect.get_x() + rect.get_width() * .5,
height + margin,
fmt % height,
ha='center', va='bottom')
else:
raise NotImplementedError('unhandled where: %r' % where)

Expand Down

0 comments on commit a4273cd

Please sign in to comment.