diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index c2355d2..87c0a95 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,3 +1,20 @@
+What's new in version 0.3
+-------------------------
+
+- Added `from_contents` to provide an alternative, intuitive way of specifying
+  category membership of elements.
+- Fixed the display of the "intersection size" label on plots, which had been
+  missing.
+- Trying to improve nomenclature, upsetplot now avoids "set" to refer to the
+  top-level sets, which are now to be known as "categories". This matches the
+  intuition that categories are named, logical groupings, as opposed to
+  "subsets". To this end:
+
+  - `generate_data` now names its categories "cat1", "cat2" etc. rather than
+    "set1", "set2", etc.
+  - the `sort_sets_by` parameter has been renamed to `sort_categories_by` and
+    will be removed in version 0.5.
+
 What's new in version 0.2.1
 ---------------------------
 
diff --git a/README.rst b/README.rst
index df54da6..b7dd748 100644
--- a/README.rst
+++ b/README.rst
@@ -12,15 +12,15 @@ more readable. Documentation is at https://upsetplot.readthedocs.io.
 This ``upsetplot`` library tries to provide a simple interface backed by an
 extensible, object-oriented design.
 
-The basic input format is a `pandas.Series` containing counts
-corresponding to set intersection sizes.  The index indicates which rows
-pertain to which sets, by having multiple boolean indices, like ``example``
-in the following::
+The basic input format is a `pandas.Series` containing counts corresponding to
+subset sizes, where each subset is an intersection of named categories.  The
+index of the Series indicates which rows pertain to which categories, by having
+multiple boolean indices, like ``example`` in the following::
 
     >>> from upsetplot import generate_data
     >>> example = generate_data(aggregated=True)
     >>> example  # doctest: +NORMALIZE_WHITESPACE
-    set0   set1   set2
+    cat0   cat1   cat2
     False  False  False      56
                   True      283
            True   False    1279
@@ -43,17 +43,17 @@ makes:
 .. image:: http://upsetplot.readthedocs.io/en/latest/_images/sphx_glr_plot_generated_001.png
    :target: ../auto_examples/plot_generated.html
 
-This plot shows the cardinality of every set combination seen in our data.  The
-leftmost column counts items absent from any set. The next three columns count
-items only in ``set1``, ``set2`` and ``set3`` respectively, with following
-columns showing cardinalities for items in each combination of exactly two
-named sets. The rightmost column counts items in all three sets.
+This plot shows the cardinality of every category combination seen in our data.
+The leftmost column counts items absent from any category. The next three
+columns count items only in ``cat1``, ``cat2`` and ``cat3`` respectively, with
+following columns showing cardinalities for items in each combination of
+exactly two named sets. The rightmost column counts items in all three sets.
 
 Rotation
 ........
 
-We call the above plot style "horizontal" because the set intersections are
-presented from left to right.  `Vertical plots
+We call the above plot style "horizontal" because the category intersections
+are presented from left to right.  `Vertical plots
 <http://upsetplot.readthedocs.io/en/latest/auto_examples/plot_vertical.html>`__
 are also supported!
 
@@ -71,30 +71,29 @@ in each subset.
 .. image:: http://upsetplot.readthedocs.io/en/latest/_images/sphx_glr_plot_boston_001.png
    :target: http://upsetplot.readthedocs.io/en/latest/auto_examples/plot_boston.html
 
-
 Loading datasets
 ................
 
 While the dataset above is randomly generated, you can prepare your own dataset
 for input to upsetplot.  A helpful tool is `from_memberships`, which allows
-us to reconstruct the example above by indicating each data point's set
+us to reconstruct the example above by indicating each data point's category
 membership::
 
     >>> from upsetplot import from_memberships
     >>> example = from_memberships(
     ...     [[],
-    ...      ['set2'],
-    ...      ['set1'],
-    ...      ['set1', 'set2'],
-    ...      ['set0'],
-    ...      ['set0', 'set2'],
-    ...      ['set0', 'set1'],
-    ...      ['set0', 'set1', 'set2'],
+    ...      ['cat2'],
+    ...      ['cat1'],
+    ...      ['cat1', 'cat2'],
+    ...      ['cat0'],
+    ...      ['cat0', 'cat2'],
+    ...      ['cat0', 'cat1'],
+    ...      ['cat0', 'cat1', 'cat2'],
     ...      ],
     ...      data=[56, 283, 1279, 5882, 24, 90, 429, 1957]
     ... )
     >>> example  # doctest: +NORMALIZE_WHITESPACE
-    set0   set1   set2
+    cat0   cat1   cat2
     False  False  False      56
                   True      283
            True   False    1279
@@ -105,6 +104,8 @@ membership::
                   True     1957
     dtype: int64
 
+See also `from_contents`, another way to describe categorised data.
+
 Installation
 ------------
 
@@ -130,8 +131,8 @@ Why an alternative to py-upset?
 Probably for petty reasons. It appeared `py-upset
 <https://github.com/ImSoErgodic/py-upset>`_ was not being maintained.  Its
 input format was undocumented, inefficient and, IMO, inappropriate.  It did not
-facilitate showing plots of each set intersection distribution as in Lex et
-al's work introducing UpSet plots. Nor did it include the horizontal bar plots
+facilitate showing plots of each subset's distribution as in Lex et al's work
+introducing UpSet plots. Nor did it include the horizontal bar plots
 illustrated there. It did not support Python 2. I decided it would be easier to
 construct a cleaner version than to fix it.
 
diff --git a/upsetplot/data.py b/upsetplot/data.py
index e075ab1..640d645 100644
--- a/upsetplot/data.py
+++ b/upsetplot/data.py
@@ -12,17 +12,17 @@ def generate_data(seed=0, n_samples=10000, n_sets=3, aggregated=False):
     df = pd.DataFrame({'value': np.zeros(n_samples)})
     for i in range(n_sets):
         r = rng.rand(n_samples)
-        df['set%d' % i] = r > rng.rand()
+        df['cat%d' % i] = r > rng.rand()
         df['value'] += r
 
-    df.set_index(['set%d' % i for i in range(n_sets)], inplace=True)
+    df.set_index(['cat%d' % i for i in range(n_sets)], inplace=True)
     if aggregated:
         return df.value.groupby(level=list(range(n_sets))).count()
     return df.value
 
 
 def from_memberships(memberships, data=None):
-    """Load data where each sample has a collection of set names
+    """Load data where each sample has a collection of category names
 
     The output should be suitable for passing to `UpSet` or `plot`.
 
@@ -30,29 +30,29 @@ def from_memberships(memberships, data=None):
     ----------
     memberships : sequence of collections of strings
         Each element corresponds to a data point, indicating the sets it is a
-        member of.  Each set is named by a string.
+        member of.  Each category is named by a string.
     data : Series-like or DataFrame-like, optional
-        If given, the index of set memberships is attached to this data.
+        If given, the index of category memberships is attached to this data.
         It must have the same length as `memberships`.
         If not given, the series will contain the value 1.
 
     Returns
     -------
     DataFrame or Series
-        `data` is returned with its index indicating set membership.
+        `data` is returned with its index indicating category membership.
         It will be a Series if `data` is a Series or 1d numeric array.
-        The index will have levels ordered by set names.
+        The index will have levels ordered by category names.
 
     Examples
     --------
     >>> from upsetplot import from_memberships
     >>> from_memberships([
-    ...     ['set1', 'set3'],
-    ...     ['set2', 'set3'],
-    ...     ['set1'],
+    ...     ['cat1', 'cat3'],
+    ...     ['cat2', 'cat3'],
+    ...     ['cat1'],
     ...     []
     ... ])  # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
-    set1   set2   set3
+    cat1   cat2   cat3
     True   False  True     1
     False  True   True     1
     True   False  False    1
@@ -61,13 +61,13 @@ def from_memberships(memberships, data=None):
     >>> # now with data:
     >>> import numpy as np
     >>> from_memberships([
-    ...     ['set1', 'set3'],
-    ...     ['set2', 'set3'],
-    ...     ['set1'],
+    ...     ['cat1', 'cat3'],
+    ...     ['cat2', 'cat3'],
+    ...     ['cat1'],
     ...     []
     ... ], data=np.arange(12).reshape(4, 3))  # doctest: +NORMALIZE_WHITESPACE
                        0   1   2
-    set1  set2  set3
+    cat1  cat2  cat3
     True  False True   0   1   2
     False True  True   3   4   5
     True  False False  6   7   8
@@ -77,9 +77,9 @@ def from_memberships(memberships, data=None):
                        for names in memberships])
     for set_name in df.columns:
         if not hasattr(set_name, 'lower'):
-            raise ValueError('Set names should be strings')
+            raise ValueError('Category names should be strings')
     if df.shape[1] == 0:
-        raise ValueError('Require at least one set. None were found.')
+        raise ValueError('Require at least one category. None were found.')
     df.sort_index(axis=1, inplace=True)
     df.fillna(False, inplace=True)
     df = df.astype(bool)
@@ -118,7 +118,7 @@ def from_contents(contents, data=None, id_column='id'):
     Returns
     -------
     DataFrame
-        `data` is returned with its index indicating set membership,
+        `data` is returned with its index indicating category membership,
         including a column named according to id_column.
         If data is not given, the order of rows is not assured.
 
diff --git a/upsetplot/plotting.py b/upsetplot/plotting.py
index ae6bb72..64b5e0c 100644
--- a/upsetplot/plotting.py
+++ b/upsetplot/plotting.py
@@ -1,5 +1,6 @@
 from __future__ import print_function, division, absolute_import
 
+import warnings
 import itertools
 
 import numpy as np
@@ -9,7 +10,7 @@ from matplotlib import pyplot as plt
 from matplotlib.tight_layout import get_renderer
 
 
-def _process_data(df, sort_by, sort_sets_by, sum_over):
+def _process_data(df, sort_by, sort_categories_by, sum_over):
     if df.ndim == 1:
         data = df
         df = pd.DataFrame({'_value': df})
@@ -40,10 +41,10 @@ def _process_data(df, sort_by, sort_sets_by, sum_over):
     totals = [data[data.index.get_level_values(name).values.astype(bool)].sum()
               for name in data.index.names]
     totals = pd.Series(totals, index=data.index.names)
-    if sort_sets_by == 'cardinality':
+    if sort_categories_by == 'cardinality':
         totals.sort_values(ascending=False, inplace=True)
-    elif sort_sets_by is not None:
-        raise ValueError('Unknown sort_sets_by: %r' % sort_sets_by)
+    elif sort_categories_by is not None:
+        raise ValueError('Unknown sort_categories_by: %r' % sort_categories_by)
     df = df.reorder_levels(totals.index.values)
     data = data.reorder_levels(totals.index.values)
 
@@ -149,20 +150,23 @@ class UpSet:
     Parameters
     ----------
     data : pandas.Series or pandas.DataFrame
-        Values for each set to plot.
-        Should have multi-index where each level is binary,
-        corresponding to set membership.
+        Elements associated with categories (a DataFrame), or the size of each
+        subset of categories (a Series).
+        Should have MultiIndex where each level is binary,
+        corresponding to category membership.
         If a DataFrame, `sum_over` must be a string or False.
     orientation : {'horizontal' (default), 'vertical'}
         If horizontal, intersections are listed from left to right.
     sort_by : {'cardinality', 'degree'}
-        If 'cardinality', set intersections are listed from largest to
-        smallest value.
-        If 'degree', they are listed in order of the number of sets
+        If 'cardinality', subset are listed from largest to smallest.
+        If 'degree', they are listed in order of the number of categories
         intersected.
-    sort_sets_by : {'cardinality', None}
-        Whether to sort the overall sets by total cardinality, or leave them
+    sort_categories_by : {'cardinality', None}
+        Whether to sort the categories by total cardinality, or leave them
         in the provided order.
+
+        .. versionadded: 0.3
+            Replaces sort_sets_by
     sum_over : str, False or None (default)
         Must be specified when `data` is a DataFrame. If False, the
         intersection plot will show the count of each subset. Otherwise, it
@@ -170,8 +174,8 @@ class UpSet:
     facecolor : str
         Color for bar charts and dots.
     with_lines : bool
-        Whether to show lines joining dots in the matrix, to mark multiple sets
-        being intersected.
+        Whether to show lines joining dots in the matrix, to mark multiple
+        categories being intersected.
     element_size : float or None
         Side length in pt. If None, size is estimated to fit figure
     intersection_plot_elements : int
@@ -184,14 +188,19 @@ 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.
+    sort_sets_by
+        .. deprecated: 0.3
+            Replaced by sort_categories_by, this parameter will be removed in
+            version 0.5.
     """
     _default_figsize = (10, 6)
 
     def __init__(self, data, orientation='horizontal', sort_by='degree',
-                 sort_sets_by='cardinality', sum_over=None, facecolor='black',
+                 sort_categories_by='cardinality', sum_over=None,
+                 facecolor='black',
                  with_lines=True, element_size=32,
                  intersection_plot_elements=6, totals_plot_elements=2,
-                 show_counts=''):
+                 show_counts='', sort_sets_by='deprecated'):
 
         self._horizontal = orientation == 'horizontal'
         self._reorient = _identity if self._horizontal else _transpose
@@ -204,10 +213,15 @@ class UpSet:
                                'elements': intersection_plot_elements}]
         self._show_counts = show_counts
 
+        if sort_sets_by != 'deprecated':
+            sort_categories_by = sort_sets_by
+            warnings.warn('sort_sets_by was deprecated in version 0.3 and '
+                          'will be removed in version 0.5', DeprecationWarning)
+
         (self._df, self.intersections,
          self.totals) = _process_data(data,
                                       sort_by=sort_by,
-                                      sort_sets_by=sort_sets_by,
+                                      sort_categories_by=sort_categories_by,
                                       sum_over=sum_over)
         if not self._horizontal:
             self.intersections = self.intersections[::-1]
@@ -352,13 +366,13 @@ class UpSet:
         """
         ax = self._reorient(ax)
         data = self.intersections
-        n_sets = data.index.nlevels
+        n_cats = data.index.nlevels
 
         idx = np.flatnonzero(data.index.to_frame()[data.index.names].values)
-        c = np.array(['lightgrey'] * len(data) * n_sets, dtype='O')
+        c = np.array(['lightgrey'] * len(data) * n_cats, dtype='O')
         c[idx] = self._facecolor
-        x = np.repeat(np.arange(len(data)), n_sets)
-        y = np.tile(np.arange(n_sets), len(data))
+        x = np.repeat(np.arange(len(data)), n_cats)
+        y = np.tile(np.arange(n_cats), len(data))
         if self._element_size is not None:
             s = (self._element_size * .35) ** 2
         else:
@@ -375,7 +389,7 @@ class UpSet:
                       lw=2, colors=self._facecolor)
 
         tick_axis = ax.yaxis
-        tick_axis.set_ticks(np.arange(n_sets))
+        tick_axis.set_ticks(np.arange(n_cats))
         tick_axis.set_ticklabels(data.index.names,
                                  rotation=0 if self._horizontal else -90)
         ax.xaxis.set_visible(False)

Change nomenclature: use "category" for named sets
Use of "set" is confusing, although "named set" is slightly better.
diff --git a/upsetplot/tests/test_data.py b/upsetplot/tests/test_data.py
index 2682e61..57db0e5 100644
--- a/upsetplot/tests/test_data.py
+++ b/upsetplot/tests/test_data.py
@@ -10,9 +10,9 @@ from upsetplot import from_memberships, from_contents
 
 @pytest.mark.parametrize('typ', [set, list, tuple, iter])
 def test_from_memberships_no_data(typ):
-    with pytest.raises(ValueError, match='at least one set'):
+    with pytest.raises(ValueError, match='at least one category'):
         from_memberships([])
-    with pytest.raises(ValueError, match='at least one set'):
+    with pytest.raises(ValueError, match='at least one category'):
         from_memberships([[], []])
     with pytest.raises(ValueError, match='strings'):
         from_memberships([[1]])
diff --git a/upsetplot/tests/test_upsetplot.py b/upsetplot/tests/test_upsetplot.py
index 14fe6ca..baaa31d 100644
--- a/upsetplot/tests/test_upsetplot.py
+++ b/upsetplot/tests/test_upsetplot.py
@@ -26,16 +26,16 @@ def is_ascending(seq):
     generate_data(aggregated=True).iloc[1:-2],
 ])
 @pytest.mark.parametrize('sort_by', ['cardinality', 'degree'])
-@pytest.mark.parametrize('sort_sets_by', [None, 'cardinality'])
-def test_process_data_series(X, sort_by, sort_sets_by):
+@pytest.mark.parametrize('sort_categories_by', [None, 'cardinality'])
+def test_process_data_series(X, sort_by, sort_categories_by):
     with pytest.raises(ValueError, match='sum_over is not applicable'):
-        _process_data(X, sort_by=sort_by, sort_sets_by=sort_sets_by,
+        _process_data(X, sort_by=sort_by,
+                      sort_categories_by=sort_categories_by,
                       sum_over=False)
 
-    df, intersections, totals = _process_data(X,
-                                              sort_by=sort_by,
-                                              sort_sets_by=sort_sets_by,
-                                              sum_over=None)
+    df, intersections, totals = _process_data(
+        X, sort_by=sort_by, sort_categories_by=sort_categories_by,
+        sum_over=None)
     assert intersections.name == 'value'
     X_reordered = (X
                    .reorder_levels(intersections.index.names)
@@ -52,7 +52,7 @@ def test_process_data_series(X, sort_by, sort_sets_by):
         assert is_ascending(intersections.index.to_frame().sum(axis=1))
         # TODO: within a same-degree group, the tuple of active names should
         #       be in sort-order
-    if sort_sets_by:
+    if sort_categories_by:
         assert is_ascending(totals.values[::-1])
 
     assert np.all(totals.index.values == intersections.index.names)
@@ -67,29 +67,51 @@ def test_process_data_series(X, sort_by, sort_sets_by):
     assert len(df) == len(X)
 
 
+@pytest.mark.parametrize('sort_sets_by', [None, 'cardinality'])
+@pytest.mark.parametrize('X', [
+    generate_data(aggregated=True),
+])
+def test_sort_sets_by_deprecation(X, sort_sets_by):
+    with pytest.warns(DeprecationWarning, match='sort_sets_by'):
+        upset1 = UpSet(X, sort_sets_by=sort_sets_by)
+    with pytest.warns(None):
+        upset2 = UpSet(X, sort_categories_by=sort_sets_by)
+
+    fig = matplotlib.figure.Figure()
+    upset1.plot(fig)
+    png1 = io.BytesIO()
+    fig.savefig(png1, format='raw')
+
+    fig = matplotlib.figure.Figure()
+    upset2.plot(fig)
+    png2 = io.BytesIO()
+    fig.savefig(png2, format='raw')
+
+    assert png1.getvalue() == png2.getvalue()
+
+
 @pytest.mark.parametrize('x', [
     generate_data(aggregated=False),
 ])
 @pytest.mark.parametrize('sort_by', ['cardinality', 'degree'])
-@pytest.mark.parametrize('sort_sets_by', [None, 'cardinality'])
-def test_process_data_frame(x, sort_by, sort_sets_by):
+@pytest.mark.parametrize('sort_categories_by', [None, 'cardinality'])
+def test_process_data_frame(x, sort_by, sort_categories_by):
     X = pd.DataFrame({'a': x})
 
     with pytest.raises(ValueError, match='sum_over must be False or '):
-        _process_data(X, sort_by=sort_by, sort_sets_by=sort_sets_by,
+        _process_data(X, sort_by=sort_by,
+                      sort_categories_by=sort_categories_by,
                       sum_over=None)
 
-    df, intersections, totals = _process_data(X,
-                                              sort_by=sort_by,
-                                              sort_sets_by=sort_sets_by,
-                                              sum_over='a')
+    df, intersections, totals = _process_data(
+        X, sort_by=sort_by, sort_categories_by=sort_categories_by,
+        sum_over='a')
     assert df is not X
 
     # check equivalence to Series
-    df1, intersections1, totals1 = _process_data(x,
-                                                 sort_by=sort_by,
-                                                 sort_sets_by=sort_sets_by,
-                                                 sum_over=None)
+    df1, intersections1, totals1 = _process_data(
+        x, sort_by=sort_by, sort_categories_by=sort_categories_by,
+        sum_over=None)
 
     assert intersections.name == 'a'
     assert_frame_equal(df, df1.rename(columns={'_value': 'a'}))
@@ -98,10 +120,9 @@ def test_process_data_frame(x, sort_by, sort_sets_by):
 
     # check effect of extra column
     X = pd.DataFrame({'a': x, 'b': np.arange(len(x))})
-    df2, intersections2, totals2 = _process_data(X,
-                                                 sort_by=sort_by,
-                                                 sort_sets_by=sort_sets_by,
-                                                 sum_over='a')
+    df2, intersections2, totals2 = _process_data(
+        X, sort_by=sort_by, sort_categories_by=sort_categories_by,
+        sum_over='a')
     assert_series_equal(intersections, intersections2)
     assert_series_equal(totals, totals2)
     assert_frame_equal(df, df2.drop('b', axis=1))
@@ -109,10 +130,9 @@ def test_process_data_frame(x, sort_by, sort_sets_by):
 
     # check effect not dependent on order/name
     X = pd.DataFrame({'b': np.arange(len(x)), 'c': x})
-    df3, intersections3, totals3 = _process_data(X,
-                                                 sort_by=sort_by,
-                                                 sort_sets_by=sort_sets_by,
-                                                 sum_over='c')
+    df3, intersections3, totals3 = _process_data(
+        X, sort_by=sort_by, sort_categories_by=sort_categories_by,
+        sum_over='c')
     assert_series_equal(intersections, intersections3, check_names=False)
     assert intersections.name == 'a'
     assert intersections3.name == 'c'
@@ -122,14 +142,12 @@ def test_process_data_frame(x, sort_by, sort_sets_by):
 
     # check sum_over=False
     X = pd.DataFrame({'b': np.ones(len(x), dtype=int), 'c': x})
-    df4, intersections4, totals4 = _process_data(X,
-                                                 sort_by=sort_by,
-                                                 sort_sets_by=sort_sets_by,
-                                                 sum_over='b')
-    df5, intersections5, totals5 = _process_data(X,
-                                                 sort_by=sort_by,
-                                                 sort_sets_by=sort_sets_by,
-                                                 sum_over=False)
+    df4, intersections4, totals4 = _process_data(
+        X, sort_by=sort_by, sort_categories_by=sort_categories_by,
+        sum_over='b')
+    df5, intersections5, totals5 = _process_data(
+        X, sort_by=sort_by, sort_categories_by=sort_categories_by,
+        sum_over=False)
     assert_series_equal(intersections4, intersections5, check_names=False)
     assert intersections4.name == 'b'
     assert intersections5.name == 'size'
@@ -138,10 +156,12 @@ def test_process_data_frame(x, sort_by, sort_sets_by):
 
 
 @pytest.mark.parametrize('sort_by', ['cardinality', 'degree'])
-@pytest.mark.parametrize('sort_sets_by', [None, 'cardinality'])
-def test_not_aggregated(sort_by, sort_sets_by):
+@pytest.mark.parametrize('sort_categories_by', [None, 'cardinality'])
+def test_not_aggregated(sort_by, sort_categories_by):
     # FIXME: this is not testing if aggregation used is count or sum
-    kw = {'sort_by': sort_by, 'sort_sets_by': sort_sets_by, 'sum_over': None}
+    kw = {'sort_by': sort_by,
+          'sort_categories_by': sort_categories_by,
+          'sum_over': None}
     Xagg = generate_data(aggregated=True)
     df1, intersections1, totals1 = _process_data(Xagg, **kw)
     Xunagg = generate_data()
@@ -159,8 +179,8 @@ def test_not_aggregated(sort_by, sort_sets_by):
 @pytest.mark.parametrize('kw', [{'sort_by': 'blah'},
                                 {'sort_by': True},
                                 {'sort_by': None},
-                                {'sort_sets_by': 'blah'},
-                                {'sort_sets_by': True}])
+                                {'sort_categories_by': 'blah'},
+                                {'sort_categories_by': True}])
 def test_param_validation(kw):
     X = generate_data(n_samples=100)
     with pytest.raises(ValueError):

pip install -e .[dev]
parse_log_pytest
requirements.txt
numpy>=1.16.0 pandas>=1.0.0 scipy matplotlib numpydoc sphinx-gallery sphinx-issues seaborn scikit-learn pytest
apt-get update apt-get install -y gcc
3.6
doc/requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
attrs==22.2.0
Babel==2.11.0
certifi==2021.5.30
charset-normalizer==2.0.12
cycler==0.11.0
docutils==0.18.1
idna==3.10
imagesize==1.4.1
importlib-metadata==4.8.3
iniconfig==1.1.1
Jinja2==3.0.3
joblib==1.1.1
kiwisolver==1.3.1
MarkupSafe==2.0.1
matplotlib==3.3.4
numpy==1.19.5
numpydoc==1.1.0
packaging==21.3
pandas==1.1.5
Pillow==8.4.0
pluggy==1.0.0
py==1.11.0
Pygments==2.14.0
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
pytz==2025.2
requests==2.27.1
scikit-learn==0.24.2
scipy==1.5.4
seaborn==0.11.2
six==1.17.0
snowballstemmer==2.2.0
Sphinx==5.3.0
sphinx-gallery==0.10.0
sphinx-issues==3.0.1
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
threadpoolctl==3.1.0
tomli==1.2.3
typing_extensions==4.1.1
-e git+https://github.com/jnothman/UpSetPlot.git@3bdac289a44d88749652e38b9d0a773ecc4ac39b#egg=UpSetPlot
urllib3==1.26.20
zipp==3.6.0

name: UpSetPlot
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - attrs==22.2.0
      - babel==2.11.0
      - charset-normalizer==2.0.12
      - cycler==0.11.0
      - docutils==0.18.1
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - jinja2==3.0.3
      - joblib==1.1.1
      - kiwisolver==1.3.1
      - markupsafe==2.0.1
      - matplotlib==3.3.4
      - numpy==1.19.5
      - numpydoc==1.1.0
      - packaging==21.3
      - pandas==1.1.5
      - pillow==8.4.0
      - pluggy==1.0.0
      - py==1.11.0
      - pygments==2.14.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - requests==2.27.1
      - scikit-learn==0.24.2
      - scipy==1.5.4
      - seaborn==0.11.2
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==5.3.0
      - sphinx-gallery==0.10.0
      - sphinx-issues==3.0.1
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - threadpoolctl==3.1.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - zipp==3.6.0
prefix: /opt/conda/envs/UpSetPlot

upsetplot/tests/test_data.py::test_from_memberships_no_data[set] upsetplot/tests/test_data.py::test_from_memberships_no_data[list] upsetplot/tests/test_data.py::test_from_memberships_no_data[tuple] upsetplot/tests/test_data.py::test_from_memberships_no_data[iter] upsetplot/tests/test_upsetplot.py::test_process_data_series[None-cardinality-X0] upsetplot/tests/test_upsetplot.py::test_process_data_series[None-cardinality-X1] upsetplot/tests/test_upsetplot.py::test_process_data_series[None-degree-X0] upsetplot/tests/test_upsetplot.py::test_process_data_series[None-degree-X1] upsetplot/tests/test_upsetplot.py::test_process_data_series[cardinality-cardinality-X0] upsetplot/tests/test_upsetplot.py::test_process_data_series[cardinality-cardinality-X1] upsetplot/tests/test_upsetplot.py::test_process_data_series[cardinality-degree-X0] upsetplot/tests/test_upsetplot.py::test_process_data_series[cardinality-degree-X1] upsetplot/tests/test_upsetplot.py::test_sort_sets_by_deprecation[X0-None] upsetplot/tests/test_upsetplot.py::test_sort_sets_by_deprecation[X0-cardinality] upsetplot/tests/test_upsetplot.py::test_process_data_frame[None-cardinality-x0] upsetplot/tests/test_upsetplot.py::test_process_data_frame[None-degree-x0] upsetplot/tests/test_upsetplot.py::test_process_data_frame[cardinality-cardinality-x0] upsetplot/tests/test_upsetplot.py::test_process_data_frame[cardinality-degree-x0] upsetplot/tests/test_upsetplot.py::test_not_aggregated[None-cardinality] upsetplot/tests/test_upsetplot.py::test_not_aggregated[None-degree] upsetplot/tests/test_upsetplot.py::test_not_aggregated[cardinality-cardinality] upsetplot/tests/test_upsetplot.py::test_not_aggregated[cardinality-degree] upsetplot/tests/test_upsetplot.py::test_param_validation[kw3] upsetplot/tests/test_upsetplot.py::test_param_validation[kw4]
upsetplot/tests/test_data.py::test_from_memberships_with_data[data0-1] upsetplot/tests/test_data.py::test_from_memberships_with_data[data1-1] upsetplot/tests/test_data.py::test_from_memberships_with_data[data2-1] upsetplot/tests/test_data.py::test_from_memberships_with_data[data3-2] upsetplot/tests/test_data.py::test_from_memberships_with_data[data4-2] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[id-set-None] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[id-set-data1] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[id-list-None] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[id-list-data1] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[id-tuple-None] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[id-tuple-data1] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[id-iter-None] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[id-iter-data1] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[blah-set-None] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[blah-set-data1] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[blah-list-None] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[blah-list-data1] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[blah-tuple-None] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[blah-tuple-data1] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[blah-iter-None] upsetplot/tests/test_data.py::test_from_contents_vs_memberships[blah-iter-data1] upsetplot/tests/test_data.py::test_from_contents upsetplot/tests/test_data.py::test_from_contents_invalid[id] upsetplot/tests/test_data.py::test_from_contents_invalid[blah] upsetplot/tests/test_upsetplot.py::test_param_validation[kw0] upsetplot/tests/test_upsetplot.py::test_param_validation[kw1] upsetplot/tests/test_upsetplot.py::test_param_validation[kw2] upsetplot/tests/test_upsetplot.py::test_plot_smoke_test[kw0] upsetplot/tests/test_upsetplot.py::test_plot_smoke_test[kw1] upsetplot/tests/test_upsetplot.py::test_plot_smoke_test[kw2] upsetplot/tests/test_upsetplot.py::test_two_sets[set20-set10] upsetplot/tests/test_upsetplot.py::test_two_sets[set20-set11] upsetplot/tests/test_upsetplot.py::test_two_sets[set20-set12] upsetplot/tests/test_upsetplot.py::test_two_sets[set20-set13] upsetplot/tests/test_upsetplot.py::test_two_sets[set21-set10] upsetplot/tests/test_upsetplot.py::test_two_sets[set21-set11] upsetplot/tests/test_upsetplot.py::test_two_sets[set21-set12] upsetplot/tests/test_upsetplot.py::test_two_sets[set21-set13] upsetplot/tests/test_upsetplot.py::test_two_sets[set22-set10] upsetplot/tests/test_upsetplot.py::test_two_sets[set22-set11] upsetplot/tests/test_upsetplot.py::test_two_sets[set22-set12] upsetplot/tests/test_upsetplot.py::test_two_sets[set22-set13] upsetplot/tests/test_upsetplot.py::test_two_sets[set23-set10] upsetplot/tests/test_upsetplot.py::test_two_sets[set23-set11] upsetplot/tests/test_upsetplot.py::test_two_sets[set23-set12] upsetplot/tests/test_upsetplot.py::test_two_sets[set23-set13] upsetplot/tests/test_upsetplot.py::test_dataframe_raises upsetplot/tests/test_upsetplot.py::test_vertical upsetplot/tests/test_upsetplot.py::test_element_size upsetplot/tests/test_upsetplot.py::test_show_counts[horizontal] upsetplot/tests/test_upsetplot.py::test_show_counts[vertical] upsetplot/tests/test_upsetplot.py::test_add_catplot
README.rst CHANGELOG.rst upsetplot/data.py upsetplot/plotting.py
README.rst CHANGELOG.rst upsetplot/data.py upsetplot/plotting.py