```Date: Tue, 26 Oct 2004 23:13:33 -0400 Reply-To: "Richard A. DeVenezia" Sender: "SAS(r) Discussion" From: "Richard A. DeVenezia" Subject: Re: one random permutation > -----Original Message----- > From: SAS(r) Discussion [mailto:SAS-L@LISTSERV.UGA.EDU] On Behalf Of > nyiann Sent: Tuesday, October 26, 2004 2:13 PM > To: SAS-L@LISTSERV.UGA.EDU > Subject: one random permutation > > Hi all, > > I have a set of data I want to randomize--essentially, just one random > permutation of the dataset. I guessd the easiest way to describe it > is shifting the fields up or down a random number of positions. Is > there an easy way to do this that anyone has done before? I can't > think of any easier way than to subset each field, randomize it, then > merge the fields together again. > > N Choate, Paul@DDS wrote: > You want to sort the columns independently on different random > variables and merge them back without a by statement, just shifting > them doesn't equate to a random permutation. > > You could try it with an obs*col array, but I think that would be the > more complicated method. > Paul noted to me that the problem involved randomizing each column, not just the rows. Here are two approaches. The first is more traditional using transpose, sorts and merge. The second is quite shorter and uses hash. If you don't have character fields, the character related sections can be eliminated. ===== ONE ===== data foo; do rowid = 1 to 100; col1 + 1; col2 + 1; col3 + 1; col4 = byte (mod(col3,26)+rank('A')); length col5 \$11; col5 = repeat(col4,10); output; end; run; proc transpose data=foo out=foon(where=(_name_ ne 'rowid')); by rowid; var _numeric_; run; proc transpose data=foo out=fooc; by rowid; var _character_; run; %let seed = 7734; proc sql; create view foonr as select * from foon order by _name_,ranuni(&seed) ; create view foocr as select * from fooc order by _name_,ranuni(&seed+1) ; quit; data foonro / view=foonro; set foonr; by _name_; if first._name_ then seq=1; else seq+1; run; data foocro / view=foocro; set foocr; by _name_; if first._name_ then seq=1; else seq+1; run; proc sort data=foonro out=foonros; by seq _name_; run; proc sort data=foocro out=foocros; by seq _name_; run; proc transpose data=foonros out=foon2(drop=_name_); by seq; id _name_; var col1; run; proc transpose data=foocros out=fooc2(drop=_name_); by seq; id _name_; var col1; run; data foo_rancol; merge foon2 fooc2; by seq; run; ===== ONE ===== ===== TWO ===== data _null_; if 0 then set foo; * prep pdv; array num _numeric_; array chr _character_; * hash will act as a dynamic array ; * hash data will be all columns ; declare hash h(); h.defineKey ('_n_'); length vname \$32; do i = 1 to dim (num); call vname (num[i], vname); h.defineData (vname); end; do i = 1 to dim (chr); call vname (chr[i], vname); h.defineData (vname); end; h.defineDone(); * load table into hash; do _n_ = 1 by 1 until (end); set foo end=end; h.add(); end; * pass through data once * for each field of each row, * swap data of field in row i with data of same field in some other random row; n = _n_; do i = 1 to n; * do numeric fields; do j = 1 to dim (num); ii = ceil (n * ranuni(&seed)); _n_ = i; h.find(); holdn1 = num[j]; _n_ = ii; h.find(); holdn2 = num[j]; num[j] = holdn1; h.replace(); _n_ = i; num[j] = holdn2; h.replace(); end; * do character fields; do j = 1 to dim (chr); ii = ceil (n * ranuni(&seed)); _n_ = i; h.find(); holdc1 = chr[j]; _n_ = ii; h.find(); holdc2 = chr[j]; chr[j] = holdc1; h.replace(); _n_ = i; chr[j] = holdc2; h.replace(); end; end; h.output (dataset:'foo_rancol2'); stop; run; ===== TWO ===== -- Richard A. DeVenezia http://www.devenezia.com/ ```

Back to: Top of message | Previous page | Main SAS-L page