I want to simulate 1000 sets comprising 6 weights (w1, w2, w3, w4, w5, w6). Their values are uniformly distributed ranging from -1 to 1 (but their absolute values are greater than 0.01. The sum of their absolute values is added to 1.
Can anyone please help?
Hello @rosiecao2509,
As mkeintz has already pointed out, there is no probability distribution satisfying all your requirements. Indeed, note that for |wi| (i=1, ..., 6) with a uniform distribution on [0.01, 1] you would have the expectation E(|w1|+...+|w6|) = 6*(0.01+1)/2 = 3.03, not 1 as per your requirement.
I would probably start with a Dirichlet distribution, Dir(a). For example, consider the special case a=(1,1,1,1,1,1), which yields the uniform distribution over the set of points with positive coordinates in six-dimensional space whose coordinates sum to 1. Once you have generated a random vector (x1, ..., x6) from this distribution, you easily get corresponding weights wi: Just apply the linear transformation xi → 0.01+0.94*xi and generate a random sign.
Here is SAS code implementing this approach:
data want(drop=i j);
call streaminit(27182818);
array w[6];
array x[6] _temporary_;
do i=1 to 1000;
do j=1 to dim(w);
x[j]=rand('expo');
end;
do j=1 to dim(w);
w[j]=(2*rand('bern',0.5)-1)*(0.01+0.94*x[j]/sum(of x[*]));
end;
output;
end;
run;
(Note that the exponential distribution with default parameter 1 is the same as the Gamma(1,1) distribution mentioned in the Wikipedia article.)
In particular, this approach ensures that the six weights have the same probability distribution.
The moment you require the sum of absolute values of w1..w6 to be 1, you can no longer expect each weight w to be uniformly distributed w~uniform(-1,1).
True, you could distribute w1~uniform(-1,+1), excluding (-0.01,+0.01). Actually you'd distribute absolute |w1|~uniform(0.01,+1), and then randomly generate a positive or negative sign. Or to prevent any of w2 through w6 being less than 0.01, you would uniformly distribute |w1|~uniform(0.01,0.95).
Let's say the absolute value of |w1| is 0.4. Then you could uniformly distribute absolute |w2| over (0.01,0.55), i.e. (0.01, 0.95-0.4), and again randomly generate a sign.
You could similarly generate w3 through w5, and finally directly calculate absolute |w6| from the others, and randomly give it a sign.
But clearly the only weight distributed uniform(-1,1) is w1.
So could you clarify?
Hello @rosiecao2509,
As mkeintz has already pointed out, there is no probability distribution satisfying all your requirements. Indeed, note that for |wi| (i=1, ..., 6) with a uniform distribution on [0.01, 1] you would have the expectation E(|w1|+...+|w6|) = 6*(0.01+1)/2 = 3.03, not 1 as per your requirement.
I would probably start with a Dirichlet distribution, Dir(a). For example, consider the special case a=(1,1,1,1,1,1), which yields the uniform distribution over the set of points with positive coordinates in six-dimensional space whose coordinates sum to 1. Once you have generated a random vector (x1, ..., x6) from this distribution, you easily get corresponding weights wi: Just apply the linear transformation xi → 0.01+0.94*xi and generate a random sign.
Here is SAS code implementing this approach:
data want(drop=i j);
call streaminit(27182818);
array w[6];
array x[6] _temporary_;
do i=1 to 1000;
do j=1 to dim(w);
x[j]=rand('expo');
end;
do j=1 to dim(w);
w[j]=(2*rand('bern',0.5)-1)*(0.01+0.94*x[j]/sum(of x[*]));
end;
output;
end;
run;
(Note that the exponential distribution with default parameter 1 is the same as the Gamma(1,1) distribution mentioned in the Wikipedia article.)
In particular, this approach ensures that the six weights have the same probability distribution.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.