76 views (last 30 days)

Show older comments

Hello,

How can I generate a uniformly distributed random vector with its sum to be equal to 1?

Thank you

John D'Errico
on 14 Mar 2014

Too many people think that generating a uniform sample, then normalizing by the sum will generate a uniform sample. In fact, this is NOT at all true.

A good way to visualize this is to generate that sample for the 2-d case. For example, suppose we do it the wrong way first?

xy = rand(100,2);

plot(xy(:,1),xy(:,2),'.')

Now, lets do the sum projection that virtually everyone poses. (Yes, it is the obvious choice. Now we will see why it is the wrong approach.)

xys = bsxfun(@rdivide,xy,sum(xy,2));

hold on

plot(xys(:,1),xys(:,2),'ro')

axis equal

axis square

The sum-projected points lie along the diagonal line. Note the distribution seems to be biased towards the middle of the line. A uniform sample would have points uniformly distributed along that line.

In a low number of dimensions there are some nice tricks to generate a sample that is indeed uniform. I tend to use Roger Stafford's submission to the file exchange, randfixedsum. It is efficient, and works in any number of dimensions.

figure

xyr = randfixedsum(2,100,1,0,1)';

plot(xyr(:,1),xyr(:,2),'ro')

axis equal

axis square

Benjamin Avants
on 15 May 2014

If that's the case, I concede the point. I had interpreted the post to be asking for a single vector with uniform distribution and a total sum of 1 derived from a uniform distribution with range (0,1). I was assuming @jimaras was simply asking for a way to convert a uniform distribution (perhaps generated using the rand function) into another uniform distribution with a total sum of 1.

Further, @John stated that my approach does not yield a uniformly distributed result. I suppose this is true if you are trying to maintain uniformity in the (0,1) range, but that did not seem to be his argument. Within the new range of the scaled distribution, I believe I have shown that uniformity is maintained.

I rely on shifting and scaling pseudo-random numbers in some of my work and I felt it was important to understand if my methods were in fact impacting the uniformity of those numbers. So far, it does not seem to be the case.

I appreciate you and @John's willingness to discuss this topic at length.

Benjamin Avants
on 14 Mar 2014

You could use rand() to create a uniform distribution then divide each element by the sum.

v = rand(10,1);

vSum = sum(v);

v = v ./ vSum;

John D'Errico
on 14 May 2014

Read my answer, which does show that the simple renormalizing scheme fails to yield a uniform result.

A good way to look at it is if you think of projecting the domain from a square region onto a diagonal straight line crossing the square, you can see that the ends of the line will have fewer points that can contribute to those regions.

Your renormalizing scheme is a terribly common mistake I see made. After all, it is simple, and it seems to get the job done at first glance. It is only when you look more carefully at the actual distribution along the line that people should see it is wrong. Wrong here means non-uniform.

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!