title: Grouping by a set in pandas
body: <p>I have an example <code>df</code>:</p>
  <pre><code>import pandas as pd 
  import numpy as np
  
  
  df = pd.DataFrame({'name':['Josh', 'Paul','Ivy','Mark'],
                     'orderId':[1,2,3,4],
                     'purchases':[['sofa','sofa','chair'],
                                  ['chair','sofa'],
                                  ['sofa','chair'],
                                  ['sofa','chair','chair']]})
  </code></pre>
  <p>4 people bought the same items - <code>sofa &amp; chair</code> but in different quantities, but in general they all bought a <code>sofa</code> and a <code>chair</code> - only 1 combination of the distinct product, think of it as a <code>set(purchases)</code>.</p>
  <p>I want to answer <em>how many times each combination of purchases has been bought</em> - we know it's <code>4</code> since <code>4</code> people bought the same set of items.</p>
  <p>So I thought of this as a pseudo code where I group by the set of each <code>purchase</code> value:</p>
  <pre><code>df = df.groupby(set('purchases')).agg({'orderId':pd.Series.nunique})
  </code></pre>
  <p>But I get an error which is expected:</p>
  <blockquote>
  <p>TypeError: 'set' object is not callable</p>
  </blockquote>
  <p>I am wondering what is the best way to achieve the grouping by the <code>set</code> of a value rather then the actual value, which in this case is a list.</p>
  <p>When I tried simply grouping by the <code>purchases</code></p>
  <pre><code>df = df.groupby('purchases').agg({'orderId':pd.Series.nunique})
  </code></pre>
  <p>I get :</p>
  <blockquote>
  <p>TypeError: unhashable type: 'list'\</p>
  </blockquote>
  <p>I tried changing the lists to tuples:</p>
  <pre><code>df = pd.DataFrame({'name':['Josh', 'Paul','Ivy','Mark'],
                     'orderId':[1,2,3,4],
                     'purchases':[('sofa','sofa','chair'),
                                  ('chair','sofa'),
                                  ('sofa','chair'),
                                  ('sofa','chair','chair')]})
  </code></pre>
  <p>And then</p>
  <pre><code>df = df.groupby('purchases').agg({'purchases':lambda x:{y for y in x}}) # or set(x)
  </code></pre>
  <p>But this gives</p>
  <pre><code>                        purchases
  purchases   
  (chair, sofa)           {(chair, sofa)}
  (sofa, chair)           {(sofa, chair)}
  (sofa, chair, chair)    {(sofa, chair, chair)}
  (sofa, sofa, chair)     {(sofa, sofa, chair)}
  </code></pre>
  <p>There is still a tuple inside the set as it looks for the same tuples and not looking inside the tuple?</p>
  <p>And I tried:</p>
  <pre><code>df['purchases_unique'] = df['purchases'].apply(lambda x: set(x))
  df['# of times bought'] = df.apply(lambda x: x.value_counts())
  </code></pre>
  <p>But I get :</p>
  <blockquote>
  <p>TypeError: unhashable type: 'set'
  While the Jupyter notebook still provides an answer with log message:</p>
  </blockquote>
  <pre><code>Exception ignored in: 'pandas._libs.index.IndexEngine._call_map_locations'
  Traceback (most recent call last):
    File &quot;pandas\_libs\hashtable_class_helper.pxi&quot;, line 1709, in pandas._libs.hashtable.PyObjectHashTable.map_locations
  TypeError: unhashable type: 'set'
  {sofa, chair}    4
  </code></pre>
  <p>So in summary I am both looking for an answer how could I assign the value 4 to each of the rows so that the result would look like this:</p>
  <pre><code>name        orderId         purchases                   # of times bought
  Josh        1               (sofa, sofa, chair)         4
  Paul        2               (chair, sofa)               4
  Ivy         3               (sofa, chair)               4
  Mark        4               (sofa, chair, chair)        4
  </code></pre>
  <p>And why isn't pandas allowing to group by a <code>set</code> if python is capable of evaluating <code>{'chair', 'sofa'} == {'sofa', 'chair'}</code>?</p>