Consider a dataset of N rows with weights. This is the basic algorithm:
- Normalize the weights so that they sum to 1.
- Backup the weights into another column to record sample probabilities
- Randomly choose 1 row (without replacement), given the sample probabilities, and add it to the sample dataset
- Remove the drawn weight from the original dataset, and recompute the sample probabilities by normalizing the weights of the remaining rows
- Repeat steps 3 and 4 till sum of weights in sample reaches or exceeds threshold (assume 0.6)
Here is a toy example:
import pandas as pd
import numpy as np
def sampler(n):
df = pd.DataFrame(np.random.rand(n), columns=['weight'])
df['weight'] = df['weight']/df['weight'].sum()
df['samp_prob'] = df['weight']
samps = pd.DataFrame(columns=['weight'])
while True:
choice = np.random.choice(df.index, 1, replace=False, p=df['samp_prob'])[0]
samps.loc[choice, 'weight'] = df.loc[choice, 'weight']
df.drop(choice, axis=0, inplace=True)
df['samp_prob'] = df['weight']/df['weight'].sum()
if samps['weight'].sum() >= 0.6:
break
return samps
The problem with the toy example is the exponential growth in run times with increasing size of n:
