![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/175205/image.jpeg)
How to pick random numbers from an interval non-uniformly?
1 view (last 30 days)
Show older comments
I want to pick some numbers (N) from the interval [0,2Pi] randomly. I want all the real number in the [pi/2,pi] have probability P1 and all the others ([0,pi/2]+[pi/2pi]) have probability P2<P1. basically, the sample space has two portions: the individuals within each portion have equal probability (uniform distribution for each portion).
can I extend the "rand" function somehow to do this?
In addition, these random numbers represent "angels" of the points that should be placed on the perimeter of a circle with radius R. IF I assume uniform distribution for the whole sample space [0,2pi], is the following a correct way to choose N sample points:
angels=rand(N,1);
angels=0+(2*pi-0)*angels;
'cause most of the times the points seem to be more densely placed in some regions.
Any help would be appreciated
tnx in advance
0 Comments
Accepted Answer
Image Analyst
on 4 Jul 2014
Basically you want to do inverse transform sampling, as explained in http://en.wikipedia.org/wiki/Inverse_transform_sampling It involves taking the cumulative distribution function. I've attached a demo for picking numbers from a Rayleigh distribution.
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/175205/image.jpeg)
For more distributions you can see RANDRAW: http://www.mathworks.com/matlabcentral/fileexchange/7309-randraw
2 Comments
More Answers (2)
James Tursa
on 3 Jul 2014
Edited: James Tursa
on 3 Jul 2014
One method (assuming P1+P2=1):
A = rand(N,1);
I = A < P1; % indexes of the P1 set
A(I) = A(I)*(pi/(2*P1)); % scale the P1 set to [0,pi/2]
A(~I)=(A(~I)-P1)*(3*pi/(2*(1-P1)))+pi/2; % scale the P2 set to [pi/2,2pi]
A = mod(A+pi/2,2*pi); % shift the sets over to the desired final locations
For your circle question, yes you can simply use 2*pi*rand(N,1) to get a uniform distribution of angles in the [0,2pi] range. You can get the same result by using P1=0.25 in the code I supplied. As far as your "densely placed" observation goes, it is likely just due to not many samples being generated. Try it with a large number of samples.
3 Comments
James Tursa
on 3 Jul 2014
Can you restate your real question completely? E.g., I don't understand these comments:
choose 5 points in the intervals [pi/4,3pi/4]+[3pi/2,7pi/4].
Choose them how? Uniformly in each? Different probabilities? Or ...?
One difficulty that i am facing is that "5" is not a large number! Is there any way around this?
Why is this a difficulty?
also, if I want to use your method, do I have to just play around with the last line?
The method I gave is specific to the problem you posed. So yes, pretty much everything in the method, including the last line, might have to be adjusted or changed if there is a different problem being solved.
Your last paragraph I don't completely understand, but it seems to imply a for loop of some kind iterated on the samples. This will of course work, but will be slow if you have a lot of samples to process (may not be a concern to you).
Sam
on 3 Jul 2014
I believe this should do the trick. Just set P2 and P1 to the values you want (their exact value is not important, just their ratio). Essentially what this code does is instead of generating random numbers from 0 to 2*pi, it generates numbers from a larger range (the bigger the P1/P2 ratio, the bigger the range). It then shrinks the region from pi/2 to pi+(P1/P2-1)*pi/2 into the region pi/2 to pi, which increases the density there. Then it just offsets the remainder of the samples greater than pi so that the region from 0 to 2 pi is filled. There might be a way to do this using logical indexing instead of for loops, but I can't think of it now.
P2 = 1;
P1 = 2;
numsamples = 100000;
angles = rand(numsamples,1)*2*pi*(0.75+P1/P2/4);
for count = 1:numsamples,
if (angles(count) > pi/2) && (angles(count)<(pi+pi*(P1/P2-1)/2))
angles(count) = pi/2+(angles(count)-pi/2)/(P1/P2);
elseif angles(count)>(pi+pi*(P1/P2-1)/2)
angles(count) = angles(count) - pi*(P1/P2-1)/2;
end
end
hist(angles,200)
2 Comments
Sam
on 4 Jul 2014
Edited: Sam
on 4 Jul 2014
The 0.75 and 1/4 are from the fact that your interval of pi/2 to pi is one quarter of the total [0,2*pi] interval. Similarly, the 3/4 is because the rest is because the rest is 0.75 of the interval. As I said, the absolute values of P1 and P2 are irrelevant so you could set them equal to one with the ratio you want (so you would have P1 = 0.67 and P2 = 0.33 if you want the denser interval to have twice the density).
If you're doing stuff with the distribution, my guess would be that the for loop would not be a major chunk of the computation time. You could do a convoluted logical indexing, but I don't think it would save you much time and it would make the code much less readable. Plus it sounds from you comment below that your number N will be fairly small (like 5). In this case, I don't think you need to worry about computation time for that.
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!