Random Distribution

#!/usr/bin/python3 # ==================================================================== # Generate random numbers with a given (numerical) distribution # from: https://stackoverflow.com/questions/4265988/ # generate-random-numbers-with-a-given-numerical-distribution # ==================================================================== # The optional keyword-only argument k allows one to request more # than one sample at once. This is valuable because there is some # preparatory work that random.choices has to do every time it is # called, prior to generating any samples; by generating many samples # at once, we only have to do that preparatory work once. Here we # generate a million samples, and use collections.Counter to check # that the distribution we get roughly matches the weights we gave. # # from random import choices # population = [1, 2, 3, 4, 5, 6] # weights = [0.1, 0.05, 0.05, 0.2, 0.4, 0.2] # million_samples = choices(population, weights, k=10**6) # from collections import Counter # Counter(million_samples) # Counter({5: 399616, 6: 200387, 4: 200117, 1: 99636, # 3: 50219, 2: 50025}) # ==================================================================== import sys from random import choices population = [0,1,2,3,4,5,6,7,8,9] weights = [1,2,3,4,3,3,4,3,2,1] wtotal = 0 for w in weights: wtotal += w print(f'total-weights = {wtotal}') # ---- collect a sample of the population based on weights distribution total = 0 counts = [0 for _ in range(len(population))] for _ in range(10000): x = choices(population,weights) if len(x) > 1: print('choices returned more that one value') sys.exit() total += 1 counts[x[0]] += 1 # ---- display sample counts, etc. print(f'total = {total}') print(f'counts = {counts}') print() print(' idx weight sample') for i,c in enumerate(counts): print(f'[{i:2}] ({float(weights[i]/wtotal):<7.4}) {float(c/total):<6.4}')