Random sampling without replacement when more needs to be sampled than there are samples
<p>I need to generate samples from a list of numbers in a scenario where I might have the situation that I need to sample more numbers than I have. More explicitly, this is what I need to do: </p>

<ul>
<li><p>Let the total number of elements in my list be N.</p></li>
<li><p>I need to sample randomly without replacement from this list M samples.</p></li>
<li><p>If M &lt;= N, then simply use Numpy's random.choice without replacement. </p></li>
<li><p>If M > N, then the samples must consist X times all the N numbers in the list, where X is the number of times N fully divides M, i.e. X = floor(M/N) and then sample additional M-(X*N) remainder samples from the list without replacement. </p></li>
</ul>

<p>For example, let my list be the following: </p>

<blockquote>
  <p>L = [1, 2, 3, 4, 5]</p>
</blockquote>

<p>and I need to sample 8 samples. Then firstly, I sample the full list once and additional 3 elements randomly without replacement, e.g. my samples could then be: </p>

<blockquote>
  <p>Sampled_list = [1, 2, 3, 4, 5, 3, 5, 1]</p>
</blockquote>

<p>How can I implement such a code as efficiently as possible in terms of computation time in Python? Can this be done without for-loops? </p>

<p>At the moment I'm implementing this using for-loops but this is too inefficient for my purposes. I have also tried Numpy's random.choice without replacement but then I need to have M &lt;= N. </p>

<p>Thank you for any help! </p>

<p>Here is what might be a solution for the <strong>case where 0 &lt; M-N &lt; max(L)</strong> :</p>

<pre><code>import numpy as np
from numpy.random import random

l = np.array([1, 2, 3, 4, 5])
rand = [ i for i in l[np.argsort(np.amax(l))[:M-N]] ]

new_l = np.concatenate(l,rand)
</code></pre>

<p>Here is an example :</p>

<pre><code>l = np.array([1,2,3,4,5])
M, N = 7, len(l)
rand = [i for i in l[np.argsort(np.random(np.amax(l)))][:M-N]]
new_l = np.concatenate(l,rand)
</code></pre>

<p>And here is the output :</p>

<pre><code>new_list = np.array([1,2,3,4,5,3,4])
</code></pre>

python numpy sampling