BookmarkSubscribeRSS Feed
art297
Opal | Level 21

In response to a post earlier today I used a slightly modified version of one of Paul Dorfman's old sort macros to do what I wanted, but I was wondering if one could accomplish the same result using call sortn.  Yes, I know that the problem can be addressed with either a hash or proc surveyselect, but I'm more interested in knowing how to sort a multidimensional array based on just one of the dimensions.


In the present case I was trying to randomly assign values to 5 different groups over 10,000 iterations. e.g., I think the following does what I want to know if/how it could be done using call sortn using just one two-dimensional array:


%let n=1000;
%macro combsort (arr1 =, arr2=, order= <);
  drop __:;
  do __g = hbound (&arr1) - 1 by 0 while (__s or __g > 1);
  __g = int (__g / 1.3);
  if __g in (0 ) then __g = 1;
  else if __g in (9, 10) then __g = 11;
  __s = 0;
  do __j = lbound (&arr1) to hbound (&arr1) - __g;
  __k = __j + __g;
  if &arr1[__j] &order &arr1[__k] then continue;
  __t = &arr1[__j];
  &arr1[__j] = &arr1[__k];
  &arr1[__k] = __t;
  __t = &arr2[__j];
  &arr2[__j] = &arr2[__k];
  &arr2[__k] = __t;
  __s = 1;
  end;
  end;
%mend;
data want (keep=trial group:);
  array values(&n.);
  do until (eof);
  set hej end=eof;
  i+1;
  values(i)=y;
  end;
  array ordering(&n.);
  array group1_(%eval(&n./5));
  array group2_(%eval(&n./5));
  array group3_(%eval(&n./5));
  array group4_(%eval(&n./5));
  array group5_(%eval(&n./5));
  do trial=1 to 10000;
  do i=1 to &n.;
  ordering(i)=ranuni(0);
  end;
  %combsort(arr1=ordering, arr2=values);
  k=0;
  do i=1 to 5;
  do j=1 to %eval(&n./5);
  k+1;
  if i eq 1 then group1_(j)=values(k);
  else if i eq 2 then group2_(j)=values(k);
  else if i eq 3 then group3_(j)=values(k);
  else if i eq 4 then group4_(j)=values(k);
  else if i eq 5 then group5_(j)=values(k);
  end;
  end;
  output;
  end;
run;

7 REPLIES 7
Ksharp
Super User

Art.T

That is easy. Using macro variable to wrap these array elements.

If you know some algorithm about sorting, then you don't need function SORTN() either .

data _null_;
length x $ 200;
do i=1 to 2;
 do j=1 to 3;
  x=catx(',',x,cats('a{',i,',',j,'}'));
 end;
 call symputx(cats('a',i),x);
 call missing(x);
end;
run;
%put _user_;



data _null_;
array a{2,3} _temporary_ (2 4 1
                          5 3 2 ) ;

call sortn(&a1);
call sortn(&a2);


do i=1 to 2;
 do j=1 to 3;
  put a{i,j}= @;
 end;
 put / ;
end;
run;

Ksharp

art297
Opal | Level 21

: Thanks for trying, but not quite what I was looking for.  My example apparently wasn't sufficiently clear.  Hopefully, the following example conveys the intent better:

Have:
19 97 40 26
92 96 54 53
05 07 82 52


Want Possiblity 1 (sorted by the bottom row's values):
19 97 26 40
92 96 53 54
05 07 52 82


Want Possiblity 2 (sorted by the right most column's values):
19 97 40 26
05 07 82 52
92 96 54 53

I know how to accomplish it with some macro code sorting related one-dimensional arrays, but was hoping sortn and sortc could handle it.  Thus far, the calls don't appear to have that functionality.

Tom
Super User Tom
Super User

Why not write it to a dataset and then use proc sort?  Would easily handle the second example.  To do the first just write it out by column instead of rows.

Ksharp
Super User

Arthur.T ,

Oh. I do not think call sortn() can do this. call sortn() is only used to process an simple observation(e.g a record) , not manipulate a whole vector .For your purpose, the RETAIN statement is more suited.

Possibility 1:

data _null_;
array a{3,4} _temporary_ (19 97 40 26
                          92 96 54 53
                          05 07 82 52 ) ;
if a{1,3} gt a{1,4} then do;
          temp=a{1,4};
          a{1,4}=a{1,3};
          a{1,3}=temp;

          temp=a{2,4};
          a{2,4}=a{2,3};
          a{2,3}=temp;

          temp=a{3,4};
          a{3,4}=a{3,3};
          a{3,3}=temp;
end;


do i=1 to 3;
 do j=1 to 4;
  put a{i,j} 3. @;
 end;
 put / ;
end;
run;

Possibility 2:

data _null_;
array a{3,4} _temporary_ (19 97 40 26
                          92 96 54 53
                          05 07 82 52 ) ;
do i=1 to 3;
 do j=i+1 to 3;
  if a{i,4} gt a{j,4} then do;
          temp=a{j,4};
          a{j,4}=a{i,4};
          a{i,4}=temp;

          temp=a{j,3};
          a{j,3}=a{i,3};
          a{i,3}=temp;

           temp=a{j,2};
          a{j,2}=a{i,2};
          a{i,2}=temp;

           temp=a{j,1};
          a{j,1}=a{i,1};
          a{i,1}=temp;
     end;
 end; 
end;


do i=1 to 3;
 do j=1 to 4;
  put a{i,j} 3. @;
 end;
 put / ;
end;
run;

Ksharp

Haikuo
Onyx | Level 15

Ksharp, not to pick on you. Although temporary array is automatically retained, but there is no 'retain statement' in either of your code like you suggested. Smiley Wink

Haikuo

Ksharp
Super User

Yeah. What I mean is what TOM mean, using a dataset hold these data and use RETAIN statement to reorder these variables . I think it would be easier and better for this case.

art297
Opal | Level 21

Thanks to Tom and Ksharp.  I've marked this thread as 'assumed answered' as it appears that the answer is simply that call sortn and call sortc can't be used this way.  I'm going to stick with Paul Dorfman's macro for separating multidimensional arrays into a set of one dimensional arrays, sort the desired dimension, and shift the other arrays during the sorting process.

That approach was the most suitable in the present case as the array had to be created and sorted, on the fly, separately for each record.  Using retain, or re-writing the file and sorting it, added too many unnecessary complications.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 7 replies
  • 1963 views
  • 6 likes
  • 4 in conversation