title: How to efficiently apply combinations to a pandas DataFrame?
body: <p>so I have been working for while with a function that takes a certain df, and it applys a combinatory operation on it. Basically, it takes one column, and it create all the posible pairs between the values in that column while copying also the info in each pair.</p>
  <pre class="lang-py prettyprint-override"><code>df = pd.DataFrame({'names':[&quot;A&quot;,&quot;B&quot;,&quot;C&quot;],&quot;int&quot;:[0,1,2],&quot;str&quot;:[&quot;a&quot;,&quot;b&quot;,&quot;c&quot;]})
  +-------+------+-----+
  | names |  int | str |
  +-------+------+-----+
  | A     |    0 | &quot;a&quot; |
  | B     |    1 | &quot;b&quot; |
  | C     |    2 | &quot;C&quot; |
  +-------+------+-----+
  
  
  </code></pre>
  <p>And it transforms it into another df with this form:</p>
  <pre><code>+--------+--------+-------+-------+------+------+
  | names1 | names2 | ints1 | ints2 | str1 | str2 |
  +--------+--------+-------+-------+------+------+
  | A      | B      |     0 |     1 | &quot;a&quot;  | &quot;b&quot;  |
  | A      | C      |     0 |     2 | &quot;a&quot;  | &quot;c&quot;  |
  | B      | C      |     1 |     2 | &quot;b&quot;  | &quot;c&quot;  |
  +--------+--------+-------+-------+------+------+
  
  </code></pre>
  <p>This is the same operation as the function <a href="https://docs.python.org/3/library/itertools.html#itertools.combinations" rel="nofollow noreferrer">combinations</a> from itertools does.
  I have written a function that works well when using small databases(&lt;20MB) but I when apply the same function to dbs of 100 MB, it can take severals days to accomplish this operation due to use of <a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iterrows.html" rel="nofollow noreferrer">iterrows</a>.<br />
  <strong>My question is</strong> how can I speed up this by using other methods like apply, or np.vectorize.</p>
  <p>The function that does this with iterrows is this one:</p>
  <pre class="lang-py prettyprint-override"><code>def combinatory(data):
      # combines each name with another pair with no repetition
      # Ej: A,B,C 
      # A B data_A data_B
      # A C data_A data_C
      # B C data_B data_C
      def createpairs(data):
          import itertools
          # creates each of the pairs
          pairs = []
          n_names = data[&quot;names&quot;].unique().tolist()
          for n_names in itertools.combinations(n_names,2):
              pairs.append(n_names)
          pairs = pd.DataFrame(pairs)
          pairs.columns = [&quot;name1&quot;, &quot;name2&quot;]
          return pairs
      
      pairs = createpairs(data)
      data_1 = data.iloc[0:0]
      data_2 = data.iloc[0:0]
      for index, row in pairs.iterrows():
          # Selecting each name inside the pairs
          tray_name1 = data_1[row['name1']]
          tray_name2 = data_2[row['name2']]
          # Getting the first row of the name of each pair
          init_values_name1 = tray_name1.iloc[0]
          init_values_name2 = tray_name2.iloc[0]
          # Putting the info inside a df
          Data_name1 = Data_name1.append(init_values_name1)
          Data_name2 = Data_name2.append(init_values_name2)
      
  
      Data_fil_name1.index = range(Data_name1.shape[0])
      Data_fil_name2.index = range(Data_name2.shape[0])
      
  
      Data_end = Data_fil_name1.join(Data_fil_name2, lsuffix= '_1', rsuffix = '_2')
      Data_end = pares.join(Data_end)
  
      return Data_end
  </code></pre>