Reputation: 13
I have something like below:
random_array = np.random.random(10)
scaled_array = random_array/np.sum(random_array)
This gives me a nice array with random floats that sum to 1. However, I am trying to take this a step further and do the following:
For example, fix the 2nd and 5th elements to be 0.04 and 0.09 respectively, and generate all other elements randomly. But the sum of the whole array still needs to be exactly 1.
Taking one more step, I want to provide an upper (lower) bound for all/each element(s). For example, I still want to fix the 4th element to be 0.09 but ALSO want to force ALL elements to be LESS THAN 0.1. (They will still add up to 1 because I have more than 10 elements.)
How can I achieve this?
Upvotes: 0
Views: 241
Reputation: 627
If you want the values before scaling:
import numpy as np
random_array = np.random.random(10)
random_array[1] = 0.04
random_array[4] = 0.09
scaled_array = random_array/np.sum(random_array)
assert np.isclose(1, scaled_array.sum())
If you want fixed values after scaling:
import numpy as np
random_array = np.random.random(10)
random_array[1] = 0
random_array[4] = 0
scaled_array = (random_array/np.sum(random_array)) * (1.0 - (0.04 + 0.09))
scaled_array[1] = 0.04
scaled_array[4] = 0.09
assert np.isclose(1, scaled_array.sum())
Upvotes: 1
Reputation: 3633
Try the string cutting approach of dirichlet distribution:
N=7 # total number of elements in result
d = {2:0.04, 5:0.09} # dictionary with index as key and values
fixed_sum = 0.
result = np.zeros(N) # placeholder numpy array
# Put the fixed elements in their place and calculate their sum
for k,v in d.items():
result[k] = v
fixed_sum = fixed_sum + v
remaining_sum = 1 - fixed_sum
# Use dirichlet distribution to get elements which sum to 1.
# Multiply with remaining_sum to get elements which sum to "remaining_sum".
remaining_arr = np.random.default_rng().dirichlet(np.ones(N-len(d)))*remaining_sum
# Get the index of result where elements are zero.
zero_indx = np.nonzero(result==0)[0]
# Place the elements of remaining_arr in the result.
result[zero_indx] = remaining_arr
Upvotes: 0