- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
The article SAS Tip: Sorting an Array in Descending Order - SAS Support Communities shows how to use call sortn (or call sortc) to sort an array in descending order, even though the call routines only support ascending order. The "trick" is to list variables in an array in reverse sequence. The example simply says to use, instead of "array x{*} v1-v5;":
array rev[*] v5-v1;
call sortn(of rev[*]);
to generate descending order for variables V1 through V5.
But what if you don't have such conveniently named variables? Let's say you have variables A, B, C, .... ,Z. and you want vars G through S to have values in descending order. There is no way to declare the needed array without naming each array element in reverse order prior to the call sortn. You can't simply use the endpoint names in the array declaration to support a descending sort.
But you can use the endpoint names to define the array and a corresponding ordered hash object, and then retrieve the descending values back into the variables from endpoint to endpoint. You do declare an array, but you don't need to list (or even know the names) of the interior variables:
data have;
input
a b c d e f g h i j k l m n o p q r s t u v w x y z;
datalines;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
run;
data want (drop=_: ii);
set have;
array vals {*} G -- S;
put "Before: " (g--s) (=);
if _n_=1 then do;
_value=.;
declare hash hh (ordered:'d',multidata:'Y');
hh.definekey('_value');
hh.definedata('_value');
hh.definedone();
declare hiter hi ('hh');
end;
do ii=1 to dim(vals);
hh.add(key:vals{ii},data:vals{ii}); *See note*;
end;
do _rc=hi.last() by 0 until (hi.prev()^=0);
ii=ii-1;
vals{ii}=_value;
end;
hh.clear();
put 'After: ' (g--s) (=);
run;
Admittedly more overhead than an array statement plus a call sortn statement, but you avoid the requirement of correctly sequencing the names of all the variables in the array. The longer the array, the more benefit from this technique.
Note:
For a couple of days, I had erroneously used the hh.replace() method, but it prevents proper tracking of duplicate key values (which is why I used the multidata:"Y" option). That has now been changed to hh.add(), which honors the duplicates.
Thank you @FreelanceReinh
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set
Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets
--------------------------