amr125 amr125 - 1 year ago 75
Python Question

python dictionary, assign random values the sum of which is a certain value

I am making a python program in which random values are generated n times, to be used as parameter values for model simulation.

I have a dictionary defining the boundaries for each parameter, for example:

parameters = {'A': random.uniform(1,10), 'B': random.uniform(20,40)}

I want to add some parameters the sum of which has to be 1, something like:

params = {'C1': random.uniform(0.0,1.0), 'C2': 1 - params['C1']}

This latter obviously doesn't work producing the
KeyError: 'C1'

I also tried something like:

params = {'A': random.uniform(1,10), 'B': random.uniform(20,40), 'C': {'C1': None,'C2': None}}

def class_fractions():
for key in params['C']:
if key == 'C1':
params['C'][key] = random.uniform(0.0,1.0)
if key == 'C2':
params['C'][key] = 1.0 - params['C'][key]

but after calling the function I get the TypeError

TypeError: unsupported operand type(s) for -: 'float' and 'NoneType'

Any suggestion?

z0r z0r
Answer Source

From your use of the for loop it looks like you may really have many more parameters than just two. In that case you can generate a list of values filled with random numbers, and then scale it to sum to one, as described in this other answer. Then iterate over a zipped view of your dictionary keys and the list items and assign the items to the dictionary.

Or, operating directly on the dictionary:

params = {k: random.uniform(0, 1) for k in ('C1', 'C2', 'C3')}
total = sum(params.values())
params = {k: (v / total) for k, v in params.items()}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download