I want to generate a random number uniformly in the sets of the form (a,b)∪(c,d)∪...∪(e,f), where a < b < c ... and a > 0, and f < 1. Is this possible with the numpy.random.uniform function?
I want to generate a random number uniformly in the sets of the form (a,b)∪(c,d)∪...∪(e,f), where a < b < c ... and a > 0, and f < 1. Is this possible with the numpy.random.uniform function?
Note: This answer was written for the original version of the question, which asked for uniform samples from the set (0, 0.3) ∪ (0.7, 1).
There are many ways you could do this. Here's one that's very concise, but it depends on the particular form of the intervals you have given:
In [16]: rng = np.random.default_rng()
In [17]: n = 1000
In [18]: x = rng.uniform(-0.3, 0.3, size=n) % 1
x is the array of n samples.
The trick is that the samples are generated on the interval (-0.3, 0.3). Then by mod'ing the values with 1, the negative values "wrap around" to the interval (0.7, 1).
If you only need to pick it once you can use np.random.choice:
import numpy as np
a, b, c, d = 0, 0.3, 0.7, 1
# Specify relative probabilities
prob = np.array([b-a, d-c])
prob = prob/prob.sum() # Normalize to sum up to one
r = np.random.choice([np.random.uniform(a, b), np.random.uniform(c, d)],
p=prob)
r
0.9662186527199109
If you need to generate many values:
n=10
R = np.array([np.random.choice([np.random.uniform(a, b),np.random.uniform(c, d)],
p=prob)
for _ in range(n)])
R
array([0.19130148, 0.24858629, 0.75106557, 0.11057559, 0.9276096 ,
0.01849698, 0.89433504, 0.99455349, 0.10128313, 0.23325187])
We can see that adding the probability parameter yield the expected result:
a,b,c,d,e,f = 0, .1, .2,.25, .5, 1
prob = np.array([b-a, d-c, f-e])
prob = prob/prob.sum()
n=10_000
R = np.array([np.random.choice([np.random.uniform(a, b),
np.random.uniform(c, d),
np.random.uniform(e, f)],
p=prob)
for _ in range(n)])
print(prob)
array([0.15384615, 0.07692308, 0.76923077])
print(R[np.logical_and(R>a, R<b)].size/n, R[np.logical_and(R>c, R<d)].size/n, R[np.logical_and(R>e, R<f)].size/n)
0.1537 0.0709 0.7754