I'm filling the rows of an array, say W, with random weights that sum to 1.
So W[,+] is = a column vector of 1s.
I can do this somewhat manually but any "cool" IML tips are appreciated.
You could try something like this:
rows = 50;
cols = 10;
W = j(rows,cols,0.0);
call randgen(W,'Normal');
zz = W[,+];
W = diag(1/zz)*W;
You could try something like this:
rows = 50;
cols = 10;
W = j(rows,cols,0.0);
call randgen(W,'Normal');
zz = W[,+];
W = diag(1/zz)*W;
Clever, thank you.
Tricky follow up -- How to fill rows of an array with random POSITIVE weights that sum to 1?
My answer: Change 'Normal' to 'Uniform'.
All you need is a relatively small modification to the original code:
rows = 50;
cols = 10;
W = j(rows,cols,0.0);
call randgen(W,'Normal');
W = abs(W);
zz = W[,+];
W = diag(1/zz)*W;
It is inefficient to generate a large diagonal matrix and use matrix multiplication for this problem. Jusrt use elementwise multiplication and division:
W = W / W[,+];
I also would not use the standard normal distribution since the expected value of the sum is zero. Use "Uniform" or some other positive distribution.
Thanks, Rick & all
What I'm doing is doing a small simulation of stock portfolio weights with some turnover.
Here's the code that I came up with:
nrow = 50; ncol = 5; w = j(nrow,ncol,.); do i = 1 to nrow(w); if ( (i = 1) | (mod(i,10) = 0) ) then do; x = j(1,ncol,.); call randgen(x,'uni'); w[i,] = x / x[+]; end; else do; w[i,] = w[i-1,]; end; end; print ((1:nrow)`) w[f=5.2] (w[,+])[l="w[,+]"];
and here's some output with line breaks manually added when the weights change:
W w[,+] 1 0.32 0.16 0.05 0.34 0.13 1 2 0.32 0.16 0.05 0.34 0.13 1 3 0.32 0.16 0.05 0.34 0.13 1 4 0.32 0.16 0.05 0.34 0.13 1 5 0.32 0.16 0.05 0.34 0.13 1 6 0.32 0.16 0.05 0.34 0.13 1 7 0.32 0.16 0.05 0.34 0.13 1 8 0.32 0.16 0.05 0.34 0.13 1 9 0.32 0.16 0.05 0.34 0.13 1 10 0.34 0.20 0.10 0.18 0.18 1 11 0.34 0.20 0.10 0.18 0.18 1 12 0.34 0.20 0.10 0.18 0.18 1 13 0.34 0.20 0.10 0.18 0.18 1 14 0.34 0.20 0.10 0.18 0.18 1 15 0.34 0.20 0.10 0.18 0.18 1 16 0.34 0.20 0.10 0.18 0.18 1 17 0.34 0.20 0.10 0.18 0.18 1 18 0.34 0.20 0.10 0.18 0.18 1 19 0.34 0.20 0.10 0.18 0.18 1 20 0.04 0.33 0.33 0.23 0.07 1 21 0.04 0.33 0.33 0.23 0.07 1
You could also use the REPEAT and SHAPE function rather than the IF-THEN/ELSE logic:
proc iml;
call randseed(1,1);
N = 10; /* group size */
k = 5; /* this many different sets of weights */
nrow = N*k;
ncol = 5;
x = j(k, ncol);
call randgen(x,'uni');
x = x / x[,+];
w = repeat(x, 1, N); /* repeat N times */
w = shape(w, nrow, ncol); /* reshape */
print ((1:nrow)`) w[f=5.2] (w[,+])[l="w[,+]"];
SIMPLEX I guess.
http://blogs.sas.com/content/iml/2012/10/08/generate-uniform-data-in-a-simplex.html
proc iml;
x=j(50,10);
call randseed(12345678);
call randgen(x,'exp');
want=x/x[,+];
print want (want[,+]);
quit;
OUTPUT:
0.0648301 0.1079199 0.0228608 0.0681767 0.0458107 0.1065728 0.035765 0.2783503 0.1591276 0.1105859 1
0.4234449 0.024438 0.0264153 0.0053757 0.1316303 0.0977695 0.0967949 0.1554417 0.0352746 0.003415 1
0.1742008 0.0759239 0.0790483 0.0362075 0.3430713 0.0753865 0.0047603 0.1608051 0.0364158 0.0141804 1
0.1496225 0.2156779 0.0218255 0.0119062 0.0464079 0.0938399 0.0561757 0.0284336 0.2126586 0.1634523 1
0.0821396 0.0694797 0.0114859 0.1006526 0.0258224 0.1618293 0.2311992 0.0830032 0.0934525 0.1409357 1
0.1093307 0.2438623 0.0497669 0.1584296 0.071123 0.1400462 0.1286981 0.0390086 0.0250962 0.0346384 1
0.0451511 0.0064224 0.0948597 0.0111992 0.5084102 0.0019754 0.1812584 0.0505699 0.0485943 0.0515594 1
0.2035252 0.1788939 0.0294778 0.1373246 0.0646985 0.1397168 0.1028051 0.0405142 0.0251605 0.0778835 1
0.1220822 0.0350727 0.0461714 0.1443178 0.0068658 0.0418933 0.0410991 0.1023764 0.3349438 0.1251775 1
0.192122 0.0198897 0.0443545 0.4800069 0.038623 0.0503297 0.0209156 0.0113073 0.1381878 0.0042635 1
0.0313845 0.032611 0.4310741 0.0631909 0.1268576 0.0189176 0.0186431 0.1067634 0.0883492 0.0822086 1
0.04946 0.1710766 0.1096673 0.1645587 0.00912 0.0177279 0.0843549 0.0618942 0.0157517 0.3163887 1
0.0856845 0.091644 0.3719427 0.0193887 0.0370685 0.0996453 0.0806509 0.016613 0.120476 0.0768863 1
0.0686816 0.2127106 0.0546567 0.0243939 0.0522649 0.5152068 0.0140101 0.016338 0.0323669 0.0093705 1
0.0694356 0.0849727 0.0147498 0.0806223 0.4150253 0.0003022 0.1023573 0.0317083 0.1042205 0.096606 1
0.0993378 0.1399166 0.0798931 0.0586677 0.1379175 0.0682676 0.055003 0.065054 0.0463719 0.2495708 1
0.2213328 0.0285721 0.0132931 0.1124621 0.155769 0.0497151 0.123782 0.0916017 0.0832244 0.1202477 1
0.0468314 0.0838247 0.0552836 0.0994477 0.1789177 0.1194976 0.2082629 0.0390825 0.0796091 0.0892429 1
0.0521256 0.2763195 0.1143827 0.1916011 0.0366984 0.0073285 0.1699003 0.0242829 0.0166806 0.1106805 1
0.0468104 0.0706336 0.0565395 0.302155 0.1257473 0.1642419 0.0964451 0.0293752 0.1077106 0.0003415 1
0.0163002 0.1576576 0.0013836 0.0559424 0.2001715 0.0234375 0.1309152 0.1452492 0.0242355 0.2447073 1
0.0952232 0.2992329 0.0895257 0.0004979 0.1149403 0.0099626 0.2233921 0.0117509 0.0325163 0.1229581 1
0.0885059 0.0114501 0.1387571 0.1362204 0.1518603 0.1607144 0.1240111 0.0054885 0.0437803 0.1392118 1
0.2873259 0.198567 0.0610863 0.1149705 0.0490104 0.0072253 0.0295308 0.0278863 0.0784847 0.1459127 1
0.0408225 0.1391669 0.014964 0.2021518 0.0708116 0.0467588 0.122211 0.0357326 0.3242727 0.0031081 1
0.0817365 0.0758352 0.0144944 0.0470948 0.0449682 0.0448977 0.4455887 0.0578968 0.1363329 0.0511548 1
0.1017831 0.0109214 0.2529835 0.0371874 0.112752 0.2030563 0.12295 0.0099204 0.0733185 0.0751275 1
0.1345763 0.0941077 0.0111666 0.1838734 0.0745686 0.1568742 0.0172288 0.0960575 0.0462091 0.1853378 1
0.1215532 0.1796445 0.140381 0.0794795 0.1966997 0.0618683 0.0573633 0.0280515 0.045623 0.0893361 1
0.0886926 0.0826849 0.1180034 0.1195067 0.2298101 0.0561909 0.1726511 0.0473202 0.042588 0.0425519 1
0.0221349 0.2454024 0.0731778 0.0972758 0.1484495 0.1146809 0.0682833 0.1102719 0.0398125 0.0805109 1
0.0059513 0.1131108 0.0746576 0.155628 0.0269511 0.0028046 0.0602186 0.0816559 0.4280088 0.0510133 1
0.1434559 0.1105319 0.2193216 0.2992068 0.0090997 0.094333 0.004108 0.0381938 0.0160713 0.065678 1
0.2217303 0.0083789 0.0682749 0.0472224 0.0582704 0.214617 0.0951426 0.0690515 0.0918572 0.1254549 1
0.0257245 0.1350998 0.0482849 0.0368581 0.3251395 0.0444965 0.0016627 0.0538019 0.1295458 0.1993864 1
0.0552674 0.3809986 0.0230707 0.1292086 0.0607931 0.0350846 0.081587 0.0128453 0.2025788 0.0185658 1
0.1075428 0.2170157 0.0016591 0.1320372 0.0278715 0.0220208 0.0072232 0.006267 0.4508596 0.027503 1
0.0538039 0.0147589 0.1754015 0.3366715 0.0996219 0.0623733 0.0187091 0.1286895 0.0579247 0.0520459 1
0.2700347 0.0066957 0.0363263 0.1981466 0.0269642 0.1036702 0.1736521 0.143819 0.0106429 0.0300483 1
0.0846778 0.1937979 0.0152793 0.1125825 0.2342719 0.1340418 0.0110438 0.0352578 0.1585657 0.0204814 1
0.2608073 0.0834937 0.1996036 0.0268523 0.0296746 0.0969509 0.0336205 0.1788419 0.0648468 0.0253084 1
0.0216348 0.0723853 0.0353566 0.2231069 0.0489804 0.1151267 0.161347 0.1784846 0.0481179 0.0954597 1
0.0235029 0.1019599 0.0160237 0.1568932 0.0284969 0.451111 0.0073747 0.0224931 0.0128773 0.1792673 1
0.0786213 0.1134368 0.084441 0.1072957 0.1786074 0.0117017 0.0418253 0.1039958 0.2714284 0.0086467 1
0.1188689 0.1365063 0.0574021 0.1620486 0.00761 0.029641 0.0075762 0.4014064 0.0195824 0.0593581 1
0.1233485 0.2155991 0.093227 0.1223969 0.2207401 0.1033752 0.0009773 0.0698694 0.025668 0.0247985 1
0.0896171 0.1503852 0.094263 0.0512589 0.0111831 0.0241438 0.1117627 0.0350864 0.05815 0.3741497 1
0.003393 0.2015791 0.1296677 0.0225987 0.2003895 0.03059 0.0559043 0.1282544 0.1612973 0.0663259 1
0.0627416 0.3756903 0.0962819 0.0039439 0.099763 0.1087502 0.0080005 0.0010637 0.1721685 0.0715964 1
0.0189294 0.1640884 0.2147821 0.2193504 0.1107373 0.1594841 0.0456326 0.0120227 0.0533695 0.0016033 1
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.