title: Drawing a bootstrap sample from a pandas.DataFrame
body: <p>I would like to draw a bootstrap sample of a <code>pandas.DataFrame</code> as efficiently as possible. Using the builtin <code>iloc</code> together with a list of integers seems to be slow:</p>
  
  <pre><code>import pandas
  import numpy as np
  # Generate some data
  n = 5000
  values = np.random.uniform(size=(n, 5))
  # Construct a pandas.DataFrame
  columns = ['a', 'b', 'c', 'd', 'e']
  df = pandas.DataFrame(values, columns=columns)
  # Bootstrap
  %timeit df.iloc[np.random.randint(n, size=n)]
  # Out: 1000 loops, best of 3: 1.46 ms per loop
  </code></pre>
  
  <p>Indexing the <code>numpy</code> array is of course much faster:</p>
  
  <pre><code>%timeit values[np.random.randint(n, size=n)]
  # Out: 10000 loops, best of 3: 159 µs per loop
  </code></pre>
  
  <p>But even extracting the values, sampling the <code>numpy</code> array, and constructing a new <code>pandas.DataFrame</code> is faster:</p>
  
  <pre><code>%timeit pandas.DataFrame(df.values[np.random.randint(n, size=n)], columns=columns)
  # Out: 1000 loops, best of 3: 302 µs per loop
  </code></pre>
  
  <p>@JohnE suggested <code>sample</code> which is unfortunately even slower:</p>
  
  <pre><code>%timeit df.sample(n, replace=True)
  # Out: 100 loops, best of 3: 5.14 ms per loop
  </code></pre>
  
  <p>@firelynx suggested <code>merge</code>:</p>
  
  <pre><code>%timeit df.merge(pandas.DataFrame(index=np.random.randint(n, size=n)), left_index=True, right_index=True, how='right')
  # Out: 1000 loops, best of 3: 1.23 ms per loop
  </code></pre>
  
  <p>Does anyone have an idea why <code>iloc</code> is so slow and/or whether there are better alternatives than extracting the values, sampling and then constructing a new <code>pandas.DataFrame</code>?</p>