Reputation: 167
I'm stuck with matrices in numpy. I need to create matrix, where sum by column will be not greater than one.
np.random.rand(3,3).round(2)
gives
array([[ 0.48, 0.73, 0.81],
[ 0.4 , 0.01, 0.32],
[ 0.44, 0.4 , 0.92]])
Is there a smart way to generate matrix with random numbers where sum by column will be not greater than one? Thank you!
Upvotes: 1
Views: 1168
Reputation: 25895
You could always make sure your values to begin with are restricted:
>>> numcols=3
>>> np.random.uniform(0,1/numcols,9).reshape(3,3)
array([[ 0.26718273, 0.29798534, 0.0309619 ],
[ 0.10923526, 0.12371555, 0.03797226],
[ 0.15974434, 0.02435774, 0.30885667]])
For a square matrix this has the benefit (maybe not?) that it works simultaneously on rows as well. You can't have rows of (0,0,1)
though.
Upvotes: 0
Reputation: 18940
Normalize the columns by a random value 0 < x <= 1, so that the sum by column will be not greater than one as you request:
>>> for i in range(3): a[:,i] = a[0,i] * a[:,i] / np.sum(a[:,i])
>>> a
array([[0.02041667, 0.42772512, 0.01939597],
[0.07875 , 0.17109005, 0.0433557 ],
[0.04083333, 0.35118483, 0.10724832]])
>>> np.sum(a,axis=0)
array([0.14, 0.95, 0.17])
Upvotes: 0
Reputation: 3968
You could do this:
x = np.random.rand(3,3)
x /= np.sum(x, axis=0)
The rationale behind this is you're dividing every column by the sum of all the values. This ensures that all columns will add to 1.
Or, you could do:
x = np.random.rand(3,3)/3
Because every number will be between [0,1]. If you squish the domain to [0,1/3], then the sum is guarranteed to be <1.
It is generally unclear what you mean when you want a restriction to the numbers but still want them to be random.
Upvotes: 2