I need to obtain a k-sized sample without replacement from a population, where each member of the population has a associated weight (W).
Numpy's random.choices will not perform this task without replacement, and random.sample won't take a weighted input.
Currently, this is what I am using:
P = np.zeros((1,Parent_number))
n=0
while n < Parent_number:
draw = random.choices(population,weights=W,k=1)
if draw not in P:
P[0,n] = draw[0]
n=n+1
P=np.asarray(sorted(P[0]))
While this works, it reqires switching back and forth from arrays, to lists and back to arrays and is, therefore, less than ideal.
I am looking for the simplest and easiest to understand solution as this code will be shared with others.
For numpy, Miriam Farber's answer is the way to go.
For pure python, the technique is to pre-weight the population and then use random.sample() to extract the values without replacement:
Note, the weights are really counts. This is important because when you sample without replacement, the count needs to be reduced by one for each selection.
You can use
np.random.choice
withreplace=False
as follows:where
vec
is your population andP
is the weight vector.For example: