diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 094af8b..55bd6c1 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,9 @@
 What's new in version 0.3
 -------------------------
 
+- To improve code legibility and intuitiveness, `sum_over=False` was deprecated
+  and a `subset_size` parameter was added.  It will have better default
+  handling of DataFrames after a short deprecation period.
 - 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
diff --git a/examples/plot_boston.py b/examples/plot_boston.py
index 8bd4c8b..d06bcf6 100644
--- a/examples/plot_boston.py
+++ b/examples/plot_boston.py
@@ -54,7 +54,7 @@ boston_df = boston_df.set_index(list(boston_above_avg.columns))
 boston_df = boston_df.assign(median_value=boston.target)
 
 # UpSet plot it!
-upset = UpSet(boston_df, sum_over=False, intersection_plot_elements=3)
+upset = UpSet(boston_df, subset_size='count', intersection_plot_elements=3)
 upset.add_catplot(value='median_value', kind='strip', color='blue')
 upset.add_catplot(value='AGE', kind='strip', color='black')
 upset.plot()
diff --git a/upsetplot/plotting.py b/upsetplot/plotting.py
index a94ee0e..380e301 100644
--- a/upsetplot/plotting.py
+++ b/upsetplot/plotting.py
@@ -10,30 +10,83 @@ from matplotlib import pyplot as plt
 from matplotlib.tight_layout import get_renderer
 
 
-def _process_data(df, sort_by, sort_categories_by, sum_over):
+def _aggregate_data(df, subset_size, sum_over):
+    """
+    Returns
+    -------
+    df : DataFrame
+        full data frame
+    aggregated : Series
+        aggregates
+    """
+    _SUBSET_SIZE_VALUES = ['auto', 'count', 'sum', 'legacy']
+    if subset_size not in _SUBSET_SIZE_VALUES:
+        raise ValueError('subset_size should be one of %s. Got %r'
+                         % (_SUBSET_SIZE_VALUES, subset_size))
     if df.ndim == 1:
-        agg = df
+        # Series
+        input_name = df.name
         df = pd.DataFrame({'_value': df})
 
-        if not agg.index.is_unique:
-            agg = (agg
-                   .groupby(level=list(range(agg.index.nlevels)))
-                   .sum())
+        if not df.index.is_unique:
+            if subset_size == 'legacy':
+                warnings.warn('From version 0.4, passing a Series as data '
+                              'with non-unqiue groups will raise an error '
+                              'unless subset_size="sum" or "count".',
+                              FutureWarning)
+            if subset_size == 'auto':
+                raise ValueError('subset_size="auto" cannot be used for a '
+                                 'Series with non-unique groups.')
         if sum_over is not None:
             raise ValueError('sum_over is not applicable when the input is a '
                              'Series')
-    elif sum_over is None:
-        raise ValueError('sum_over must be False or a column name when a '
-                         'DataFrame is input')
-    else:
-        gb = df.groupby(level=list(range(df.index.nlevels)))
-        if sum_over is False:
-            agg = gb.size()
-            agg.name = 'size'
-        elif hasattr(sum_over, 'lower'):
-            agg = gb[sum_over].sum()
+        if subset_size == 'count':
+            sum_over = False
         else:
-            raise ValueError('Unsupported value for sum_over: %r' % sum_over)
+            sum_over = '_value'
+    else:
+        # DataFrame
+        if subset_size == 'legacy' and sum_over is None:
+            raise ValueError('Please specify subset_size or sum_over for a '
+                             'DataFrame.')
+        elif subset_size == 'legacy' and sum_over is False:
+            warnings.warn('sum_over=False will not be supported from version '
+                          '0.4. Use subset_size="auto" or "count" '
+                          'instead.', DeprecationWarning)
+        elif subset_size in ('auto', 'sum') and sum_over is False:
+            # remove this after deprecation
+            raise ValueError('sum_over=False is not supported when '
+                             'subset_size=%r' % subset_size)
+        elif subset_size == 'auto' and sum_over is None:
+            sum_over = False
+        elif subset_size == 'count':
+            if sum_over is not None:
+                raise ValueError('sum_over cannot be set if subset_size=%r' %
+                                 subset_size)
+            sum_over = False
+        elif subset_size == 'sum':
+            if sum_over is None:
+                raise ValueError('sum_over should be a field name if '
+                                 'subset_size="sum" and a DataFrame is '
+                                 'provided.')
+
+    gb = df.groupby(level=list(range(df.index.nlevels)))
+    if sum_over is False:
+        aggregated = gb.size()
+        aggregated.name = 'size'
+    elif hasattr(sum_over, 'lower'):
+        aggregated = gb[sum_over].sum()
+    else:
+        raise ValueError('Unsupported value for sum_over: %r' % sum_over)
+
+    if aggregated.name == '_value':
+        aggregated.name = input_name
+
+    return df, aggregated
+
+
+def _process_data(df, sort_by, sort_categories_by, subset_size, sum_over):
+    df, agg = _aggregate_data(df, subset_size, sum_over)
 
     # check all indices are boolean
     assert all(set([True, False]) >= set(level) for level in agg.index.levels)
@@ -167,10 +220,31 @@ class UpSet:
 
         .. 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
-        shows the sum of the specified field.
+    subset_size : {'auto', 'count', 'sum'}
+        Configures how to calculate the size of a subset. Choices are:
+
+        'auto'
+            If `data` is a DataFrame, count the number of rows in each group,
+            unless `sum_over` is specified.
+            If `data` is a Series with at most one row for each group, use
+            the value of the Series. If `data` is a Series with more than one
+            row per group, raise a ValueError.
+        'count'
+            Count the number of rows in each group.
+        'sum'
+            Sum the value of the `data` Series, or the DataFrame field
+            specified by `sum_over`.
+
+        Until version 0.4, the default is 'legacy' which uses `sum_over` to
+        control this behaviour. From version 0.4, 'auto' will be default.
+    sum_over : str or None
+        If `subset_size='sum'` or `'auto'`, then the intersection size is the
+        sum of the specified field in the `data` DataFrame. If a Series, only
+        None is supported and its value is summed.
+
+        If `subset_size='legacy'`, `sum_over` must be specified when `data` is
+        a DataFrame. If False, the intersection plot will show the count of
+        each subset. Otherwise, it shows the sum of the specified field.
     facecolor : str
         Color for bar charts and dots.
     with_lines : bool
@@ -196,7 +270,8 @@ class UpSet:
     _default_figsize = (10, 6)
 
     def __init__(self, data, orientation='horizontal', sort_by='degree',
-                 sort_categories_by='cardinality', sum_over=None,
+                 sort_categories_by='cardinality',
+                 subset_size='legacy', sum_over=None,
                  facecolor='black',
                  with_lines=True, element_size=32,
                  intersection_plot_elements=6, totals_plot_elements=2,
@@ -222,6 +297,7 @@ class UpSet:
          self.totals) = _process_data(data,
                                       sort_by=sort_by,
                                       sort_categories_by=sort_categories_by,
+                                      subset_size=subset_size,
                                       sum_over=sum_over)
         if not self._horizontal:
             self.intersections = self.intersections[::-1]

sum_over should default to False for DataFrame input
diff --git a/upsetplot/tests/test_upsetplot.py b/upsetplot/tests/test_upsetplot.py
index baaa31d..1a9d4c3 100644
--- a/upsetplot/tests/test_upsetplot.py
+++ b/upsetplot/tests/test_upsetplot.py
@@ -15,34 +15,39 @@ from upsetplot import UpSet
 from upsetplot import generate_data
 from upsetplot.plotting import _process_data
 
+# TODO: warnings should raise errors
+
 
 def is_ascending(seq):
     # return np.all(np.diff(seq) >= 0)
     return sorted(seq) == list(seq)
 
 
-@pytest.mark.parametrize('X', [
+@pytest.mark.parametrize('x', [
     generate_data(aggregated=True),
     generate_data(aggregated=True).iloc[1:-2],
 ])
 @pytest.mark.parametrize('sort_by', ['cardinality', 'degree'])
 @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_categories_by=sort_categories_by,
-                      sum_over=False)
+def test_process_data_series(x, sort_by, sort_categories_by):
+    assert x.name == 'value'
+    for subset_size in ['auto', 'legacy', 'sum', 'count']:
+        for sum_over in ['abc', False]:
+            with pytest.raises(ValueError, match='sum_over is not applicable'):
+                _process_data(x, sort_by=sort_by,
+                              sort_categories_by=sort_categories_by,
+                              subset_size=subset_size, sum_over=sum_over)
 
     df, intersections, totals = _process_data(
-        X, sort_by=sort_by, sort_categories_by=sort_categories_by,
-        sum_over=None)
+        x, subset_size='auto', sort_by=sort_by,
+        sort_categories_by=sort_categories_by, sum_over=None)
     assert intersections.name == 'value'
-    X_reordered = (X
+    x_reordered = (x
                    .reorder_levels(intersections.index.names)
                    .reindex(index=intersections.index))
-    assert len(X) == len(X_reordered)
-    assert X_reordered.index.is_unique
-    assert_series_equal(X_reordered, intersections,
+    assert len(x) == len(x_reordered)
+    assert x_reordered.index.is_unique
+    assert_series_equal(x_reordered, intersections,
                         check_dtype=False)
 
     if sort_by == 'cardinality':
@@ -59,23 +64,65 @@ def test_process_data_series(X, sort_by, sort_categories_by):
 
     assert np.all(df.index.names == intersections.index.names)
     assert set(df.columns) == {'_value', '_bin'}
-    assert_index_equal(df['_value'].reorder_levels(X.index.names).index,
-                       X.index)
-    assert_array_equal(df['_value'], X)
+    assert_index_equal(df['_value'].reorder_levels(x.index.names).index,
+                       x.index)
+    assert_array_equal(df['_value'], x)
     assert_index_equal(intersections.iloc[df['_bin']].index,
                        df.index)
-    assert len(df) == len(X)
+    assert len(df) == len(x)
+
+
+@pytest.mark.parametrize('x', [
+    generate_data(),
+    generate_data(aggregated=True),
+])
+def test_subset_size_series(x):
+    kw = {'sort_by': 'cardinality',
+          'sort_categories_by': 'cardinality',
+          'sum_over': None}
+    df_sum, intersections_sum, totals_sum = _process_data(
+        x, subset_size='sum', **kw)
+
+    if x.index.is_unique:
+        expected_warning = None
+    else:
+        expected_warning = FutureWarning
+    with pytest.warns(expected_warning):
+        df, intersections, totals = _process_data(
+            x, subset_size='legacy', **kw)
+    assert_frame_equal(df, df_sum)
+    assert_series_equal(intersections, intersections_sum)
+    assert_series_equal(totals, totals_sum)
+
+    if x.index.is_unique:
+        df, intersections, totals = _process_data(
+            x, subset_size='auto', **kw)
+        assert_frame_equal(df, df_sum)
+        assert_series_equal(intersections, intersections_sum)
+        assert_series_equal(totals, totals_sum)
+    else:
+        with pytest.raises(ValueError):
+            _process_data(
+                x, subset_size='auto', **kw)
+
+    df_count, intersections_count, totals_count = _process_data(
+        x, subset_size='count', **kw)
+    df, intersections, totals = _process_data(
+        x.groupby(level=list(range(len(x.index.levels)))).count(),
+        subset_size='sum', **kw)
+    assert_series_equal(intersections, intersections_count, check_names=False)
+    assert_series_equal(totals, totals_count)
 
 
 @pytest.mark.parametrize('sort_sets_by', [None, 'cardinality'])
-@pytest.mark.parametrize('X', [
+@pytest.mark.parametrize('x', [
     generate_data(aggregated=True),
 ])
-def test_sort_sets_by_deprecation(X, sort_sets_by):
+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)
+        upset1 = UpSet(x, sort_sets_by=sort_sets_by)
     with pytest.warns(None):
-        upset2 = UpSet(X, sort_categories_by=sort_sets_by)
+        upset2 = UpSet(x, sort_categories_by=sort_sets_by)
 
     fig = matplotlib.figure.Figure()
     upset1.plot(fig)
@@ -98,20 +145,21 @@ def test_sort_sets_by_deprecation(X, sort_sets_by):
 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 '):
+    with pytest.raises(ValueError, match='Please specify subset_size'):
         _process_data(X, sort_by=sort_by,
                       sort_categories_by=sort_categories_by,
-                      sum_over=None)
+                      subset_size='legacy', sum_over=None)
 
-    df, intersections, totals = _process_data(
-        X, sort_by=sort_by, sort_categories_by=sort_categories_by,
-        sum_over='a')
+    with pytest.warns(None):
+        df, intersections, totals = _process_data(
+            X, sort_by=sort_by, sort_categories_by=sort_categories_by,
+            sum_over='a', subset_size='auto')
     assert df is not X
 
     # check equivalence to Series
     df1, intersections1, totals1 = _process_data(
         x, sort_by=sort_by, sort_categories_by=sort_categories_by,
-        sum_over=None)
+        subset_size='sum', sum_over=None)
 
     assert intersections.name == 'a'
     assert_frame_equal(df, df1.rename(columns={'_value': 'a'}))
@@ -122,7 +170,7 @@ def test_process_data_frame(x, sort_by, sort_categories_by):
     X = pd.DataFrame({'a': x, 'b': np.arange(len(x))})
     df2, intersections2, totals2 = _process_data(
         X, sort_by=sort_by, sort_categories_by=sort_categories_by,
-        sum_over='a')
+        sum_over='a', subset_size='auto')
     assert_series_equal(intersections, intersections2)
     assert_series_equal(totals, totals2)
     assert_frame_equal(df, df2.drop('b', axis=1))
@@ -132,7 +180,7 @@ def test_process_data_frame(x, sort_by, sort_categories_by):
     X = pd.DataFrame({'b': np.arange(len(x)), 'c': x})
     df3, intersections3, totals3 = _process_data(
         X, sort_by=sort_by, sort_categories_by=sort_categories_by,
-        sum_over='c')
+        sum_over='c', subset_size='auto')
     assert_series_equal(intersections, intersections3, check_names=False)
     assert intersections.name == 'a'
     assert intersections3.name == 'c'
@@ -140,14 +188,14 @@ def test_process_data_frame(x, sort_by, sort_categories_by):
     assert_frame_equal(df.rename(columns={'a': 'c'}), df3.drop('b', axis=1))
     assert_array_equal(df3['b'], X['b'])
 
-    # check sum_over=False
+    # check subset_size='count'
     X = pd.DataFrame({'b': np.ones(len(x), dtype=int), 'c': x})
     df4, intersections4, totals4 = _process_data(
         X, sort_by=sort_by, sort_categories_by=sort_categories_by,
-        sum_over='b')
+        sum_over='b', subset_size='auto')
     df5, intersections5, totals5 = _process_data(
         X, sort_by=sort_by, sort_categories_by=sort_categories_by,
-        sum_over=False)
+        subset_size='count', sum_over=None)
     assert_series_equal(intersections4, intersections5, check_names=False)
     assert intersections4.name == 'b'
     assert intersections5.name == 'size'
@@ -155,12 +203,68 @@ def test_process_data_frame(x, sort_by, sort_categories_by):
     assert_frame_equal(df4, df5)
 
 
+@pytest.mark.parametrize('x', [
+    generate_data(),
+    generate_data(aggregated=True),
+])
+def test_subset_size_frame(x):
+    kw = {'sort_by': 'cardinality',
+          'sort_categories_by': 'cardinality'}
+    X = pd.DataFrame({'x': x})
+    df_sum, intersections_sum, totals_sum = _process_data(
+        X, subset_size='sum', sum_over='x', **kw)
+    df_count, intersections_count, totals_count = _process_data(
+        X, subset_size='count', sum_over=None, **kw)
+
+    # error cases: sum_over=False
+    for subset_size in ['auto', 'sum', 'count']:
+        with pytest.raises(ValueError, match='sum_over'):
+            _process_data(
+                X, subset_size=subset_size, sum_over=False, **kw)
+
+    with pytest.raises(ValueError, match='sum_over'):
+        _process_data(
+            X, subset_size=subset_size, sum_over=False, **kw)
+
+    # error cases: sum_over incompatible with subset_size
+    with pytest.raises(ValueError, match='sum_over should be a field'):
+        _process_data(
+            X, subset_size='sum', sum_over=None, **kw)
+    with pytest.raises(ValueError, match='sum_over cannot be set'):
+        _process_data(
+            X, subset_size='count', sum_over='x', **kw)
+
+    # check subset_size='auto' or 'legacy' with sum_over=str => sum
+    for subset_size in ['auto', 'legacy']:
+        df, intersections, totals = _process_data(
+            X, subset_size=subset_size, sum_over='x', **kw)
+        assert_frame_equal(df, df_sum)
+        assert_series_equal(intersections, intersections_sum)
+        assert_series_equal(totals, totals_sum)
+
+    # check subset_size='auto' with sum_over=None => count
+    df, intersections, totals = _process_data(
+        X, subset_size='auto', sum_over=None, **kw)
+    assert_frame_equal(df, df_count)
+    assert_series_equal(intersections, intersections_count)
+    assert_series_equal(totals, totals_count)
+
+    # check legacy use of sum_over=False
+    with pytest.warns(DeprecationWarning, match='sum_over=False'):
+        df, intersections, totals = _process_data(
+            X, subset_size='legacy', sum_over=False, **kw)
+    assert_frame_equal(df, df_count)
+    assert_series_equal(intersections, intersections_count)
+    assert_series_equal(totals, totals_count)
+
+
 @pytest.mark.parametrize('sort_by', ['cardinality', 'degree'])
 @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_categories_by': sort_categories_by,
+          'subset_size': 'sum',
           'sum_over': None}
     Xagg = generate_data(aggregated=True)
     df1, intersections1, totals1 = _process_data(Xagg, **kw)
@@ -182,7 +286,7 @@ def test_not_aggregated(sort_by, sort_categories_by):
                                 {'sort_categories_by': 'blah'},
                                 {'sort_categories_by': True}])
 def test_param_validation(kw):
-    X = generate_data(n_samples=100)
+    X = generate_data(n_samples=100, aggregated=True)
     with pytest.raises(ValueError):
         UpSet(X, **kw)
 
@@ -192,7 +296,7 @@ def test_param_validation(kw):
                                 {'orientation': 'vertical'}])
 def test_plot_smoke_test(kw):
     fig = matplotlib.figure.Figure()
-    X = generate_data(n_samples=100)
+    X = generate_data(n_samples=100, aggregated=True)
     plot(X, fig, **kw)
     fig.savefig(io.BytesIO(), format='png')
 
@@ -213,7 +317,7 @@ def test_two_sets(set1, set2):
     plot(pd.DataFrame({'val': [5, 7],
                        'set1': set1,
                        'set2': set2}).set_index(['set1', 'set2'])['val'],
-         fig)
+         fig, subset_size='sum')
 
 
 def test_dataframe_raises():
@@ -221,12 +325,12 @@ def test_dataframe_raises():
     df = pd.DataFrame({'val': [5, 7],
                        'set1': [False, True],
                        'set2': [True, True]}).set_index(['set1', 'set2'])
-    with pytest.raises(ValueError, match='sum_over must be'):
+    with pytest.raises(ValueError, match='Please specify subset_size or '):
         plot(df, fig)
 
 
 def test_vertical():
-    X = generate_data(n_samples=100)
+    X = generate_data(n_samples=100, aggregated=True)
 
     fig = matplotlib.figure.Figure()
     UpSet(X, orientation='horizontal').make_grid(fig)
@@ -245,7 +349,7 @@ def test_vertical():
 
 
 def test_element_size():
-    X = generate_data(n_samples=100)
+    X = generate_data(n_samples=100, aggregated=True)
     figsizes = []
     for element_size in range(10, 50, 5):
         fig = matplotlib.figure.Figure()
@@ -285,7 +389,7 @@ def _count_descendants(el):
 @pytest.mark.parametrize('orientation', ['horizontal', 'vertical'])
 def test_show_counts(orientation):
     fig = matplotlib.figure.Figure()
-    X = generate_data(n_samples=100)
+    X = generate_data(n_samples=100, aggregated=True)
     plot(X, fig)
     n_artists_no_sizes = _count_descendants(fig)
 
@@ -305,7 +409,7 @@ def test_show_counts(orientation):
 
 def test_add_catplot():
     pytest.importorskip('seaborn')
-    X = generate_data(n_samples=100)
+    X = generate_data(n_samples=100, aggregated=True)
     upset = UpSet(X)
     # smoke test
     upset.add_catplot('violin')
@@ -322,7 +426,7 @@ def test_add_catplot():
     X = generate_data(n_samples=100)
     X.name = 'foo'
     X = X.to_frame()
-    upset = UpSet(X, sum_over=False)
+    upset = UpSet(X, subset_size='count')
     # must provide value with DataFrame
     with pytest.raises(ValueError):
         upset.add_catplot('violin')

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-xdist pytest-mock pytest-asyncio 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
coverage==6.2
cycler==0.11.0
docutils==0.18.1
execnet==1.9.0
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
pytest-asyncio==0.16.0
pytest-cov==4.0.0
pytest-mock==3.6.1
pytest-xdist==3.0.2
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@51ef40df8188022977433d5cf752d971bd37efc7#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
      - coverage==6.2
      - cycler==0.11.0
      - docutils==0.18.1
      - execnet==1.9.0
      - 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
      - pytest-asyncio==0.16.0
      - pytest-cov==4.0.0
      - pytest-mock==3.6.1
      - pytest-xdist==3.0.2
      - 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_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_subset_size_series[x0] upsetplot/tests/test_upsetplot.py::test_subset_size_series[x1] 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_subset_size_frame[x0] upsetplot/tests/test_upsetplot.py::test_subset_size_frame[x1] 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_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_add_catplot
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_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_param_validation[kw3] upsetplot/tests/test_upsetplot.py::test_param_validation[kw4] 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_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]
CHANGELOG.rst upsetplot/plotting.py examples/plot_boston.py
CHANGELOG.rst upsetplot/plotting.py examples/plot_boston.py