elenaby
elenaby

Reputation: 167

random matrix with sum of values by column not greater than one

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

Answers (3)

kabanus
kabanus

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

fferri
fferri

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

OneRaynyDay
OneRaynyDay

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

Related Questions