Drawing a random number from set of numbers excluding those given in certain sets
<p>Suppose I have a two arrays:</p>

<pre><code>import numpy as np
a = np.random.randint(0,10,10)
b = np.random.randint(0,10,10)
</code></pre>

<p>I want to generate another length-10 array whose i-th entry is a random integer drawn from the set (<code>{0...9}</code> <strong>minus</strong> the elements <code>a[i]</code> and <code>b[i]</code>).</p>

<p>Being a relative rookie when it comes to NumPy, I thought the easiest way to do this might be:</p>

<ol>
<li>obtain the set difference <code>x = {0...9} - (a[i] union b[i])</code> for each <code>i</code></li>
<li>do <code>np.random.choice(x[i], 1)</code> for each <code>i</code></li>
</ol>

<p>But I'm finding this a little tricky because I can't figure out how to map <code>setdiff1d</code> elementwise across 2 arrays. Is there an obvious way to do this in NumPy (i.e. ideally without having to resort to Python sets etc.)?</p>

<p>The <code>np.random.choice</code> function seems to not allow to operate on several sets at once.  Thus, you will need some form of loop to make the separate calls to <code>np.random.choice</code> for each element of the output.  Given that a loop is needed, I don't think one can do much better than your suggestion in the question.  The following code implements your idea and hides the required loop a bit by using a list comprehension:</p>

<pre><code>import numpy as np
a = np.random.randint(0,10,10)
b = np.random.randint(0,10,10)
domain = set(range(10))
res = [ np.random.choice(list(domain - set(avoid))) for avoid in zip(a, b) ]
res = np.array(res)
</code></pre>

python numpy