Statistical programming, matrix languages, and more

How to fill rows of an array with random weights that sum to 1?

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 14
Accepted Solution

How to fill rows of an array with random weights that sum to 1?

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.


Accepted Solutions
Solution
‎10-11-2016 12:19 PM
SAS Employee
Posts: 9

Re: How to fill rows of an array with random weights that sum to 1?

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;

View solution in original post


All Replies
Solution
‎10-11-2016 12:19 PM
SAS Employee
Posts: 9

Re: How to fill rows of an array with random weights that sum to 1?

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;
Occasional Contributor
Posts: 14

Re: How to fill rows of an array with random weights that sum to 1?

[ Edited ]

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'.

SAS Employee
Posts: 9

Re: How to fill rows of an array with random weights that sum to 1?

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;
SAS Super FREQ
Posts: 3,234

Re: How to fill rows of an array with random weights that sum to 1?

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.

 

Occasional Contributor
Posts: 14

Re: How to fill rows of an array with random weights that sum to 1?

[ Edited ]

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

 

SAS Super FREQ
Posts: 3,234

Re: How to fill rows of an array with random weights that sum to 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[,+]"];
Grand Advisor
Posts: 9,335

Re: How to fill rows of an array with random weights that sum to 1?

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
Post a Question
Discussion Stats
  • 7 replies
  • 347 views
  • 5 likes
  • 4 in conversation