Rearranging variables in a sas dataset- alphabetical order - sas

I have like 500 columns of dataset, and I want to rearrange all the variables in an alphabetical order. How can I do that in any other way than using retain statement before set statement?

You can generate the list of variable names dynamically, and create a new dataset using PROC SQL.
proc sql ;
select name into :VARLIST separated by ', '
from dictionary.columns
where libname = 'SASHELP'
and memname = 'CLASS'
order by name ;
quit ;
proc sql ;
create table ordered as
select &VARLIST
from sashelp.class ;
quit ;

Related

Variable in a list datastep SAS

Suppose that I have the following list
proc sql;
select name into: list separated by ' ' from dataset;
quit;
and I want to keep the elements of this list in my dataset2. The datastep
data dataset2;
set dataset2;
if name in &list.;
run;
does not work. How should I modify the first proc sql so that the datastep makes sense? Thanks in advance!
This assumes you're looking to filter values within a column, not the number of columns.
If the value is numeric this is what you need:
data dataset3;
set dataset2;
if name not in (&list.);
run;
If the value is character then this is what you need:
proc sql;
select quote(name) into: list separated by ' ' from dataset;
quit;
data dataset3;
set dataset2;
if name not in (&list.);
run;

sas: how to create a variable containing a list of different variables in 2 datasets

I'm kinda new to SAS.
I have 2 datasets: set1 and set2.
I'd like to get a list of variables that's in set2 but not in set1.
I know I can easily see them by doing proc compare and then listvar,
however, i wish to copy&paste the whole list of different variables instead of copying one by one from the report generated.
i want either a macro variable containing a list of all different variables separated by space, or printing out all variables in plain texts that I can easily copy everything.
proc contents data=set1 out=cols1;
proc contents data=set2 out=cols2;
data common;
merge cols1 (in=a) cols2 (in=b);
by name;
if not a and b;
keep name;
run;
proc sql;
select name into :commoncols separated by ','
from work.common;
quit;
Get the list of variable names and then compare the lists.
Conceptually the simplest way see what is in a dataset is to use proc contents.
proc contents data=set1 noprint out=content1 ; run;
proc contents data=set2 noprint out=content2 ; run;
Now you just need to find the names that are in one and not the other.
An easy way is with PROC SQL set operations.
proc sql ;
create table in1_not_in2 as
select name from content1
where upcase(name) not in (select upcase(name) from content2)
;
create table in2_not_in1 as
select name from content2
where upcase(name) not in (select upcase(name) from content1)
;
quit;
You could also push the lists into macro variables instead of datasets.
proc sql noprint ;
select name from content1
into :in1_not_in2 separated by ' '
where upcase(name) not in (select upcase(name) from content2)
;
select name from content2
into :in2_not_in1 separated by ' '
where upcase(name) not in (select upcase(name) from content1)
;
quit;
Then you could use the macro variables to generate other code.
data both;
set set1(drop=&in1_not_in2) set2(drop=&in2_not_in1) ;
run;

SAS Reverse Column Order

Issue:
I'm looking to reverse the order of all columns in a sas dataset. Should I achieve this by first transposing and then using a loop to reverse the order of the columns? This is my logic...
Step One:
data pre_transpose;
set sashelp.class;
*set &&dataset&i.. ;
_row_ + 1; * Unique identifier ;
length _charvar_ $20; * Create 1 character variable ;
run;
Step One Output:
Step Two: Do I Reverse Columns Here?
proc transpose data = pre_transpose out = middle (where = (lowcase(_name_) ne '_row_'));
by _row_;
var _all_;
quit;
Step Two Output:
EDIT:
I have attempted this:
/* use proc sql to create a macro variable for column names */
proc sql noprint;
select varnum, nliteral(name)
into :varlist, :varlist separated by ' '
from dictionary.columns
where libname = 'WORK' and memname = 'all_character'
order by varnum desc;
quit;
/* Use retain to maintain format */
data reverse_columns;
retain &varlist.;
set all_character;
run;
But I did not achieve the results I was looking for - the column order is not reversed.
You just need to get the list of variable names. One way is to use the metadata. Do if your dataset is member HAVE in libref WORK then you could use this to get the list of variable names into a single macro variable.
proc sql noprint;
select varnum , nliteral(name)
into :varlist, :varlist separated by ' '
from dictionary.columns
where libname='WORK' and memname='HAVE'
order by varnum desc
;
quit;
You could then use the macro variable in a data step like this.
data want ;
retain &varlist ;
set have ;
run;
Note that the value of libname and memname in DICTIONARY.COLUMNS is in uppercase only.

finding max of many columns using proc sql statement

I am trying to write a PROC SQL query in SAS to determine maximum of many columns starting with a particular letter (say RF*). The existing proc means statement which i have goes like this.
proc means data = input_table nway noprint missing;
var age x y z RF: ST: ;
class a b c;
output out = output_table (drop = _type_ _freq_) max=;
run;
Where the columns RF: refers to all columns starting with RF and likewise for ST. I was wondering if there is something similar in PROC SQL, which i can use?
Thanks!
Dynamic SQL is indeed the way to go with this, if you must use SQL. The good news is that you can do it all in one proc sql call using only one macro variable, e.g.:
proc sql noprint;
select catx(' ','max(',name,') as',name) into :MAX_LIST separated by ','
from dictionary.columns
where libname = 'SASHELP'
and memname = 'CLASS'
and type = 'num'
/*eq: is not available in proc sql in my version of SAS, but we can use substr to match partial variable names*/
and upcase(substr(name,1,1)) in ('A','W') /*Match all numeric vars that have names starting with A or W*/
;
create table want as select SEX, &MAX_LIST
from sashelp.class
group by SEX;
quit;

Renaming Column with Dynamic Name

I have a column name from a .xls file (using excelcs engine for importing) which is dynamic and changes from day to day.
I am wondering how to do reference and rename that dynamic column name within sas without knowing before hand what it will be called?
This depends some on how it dynamically changes. If it is entirely unpredictable - you cannot write code to figure it out, or to eliminate the other known columns - your simplest option may be to use GETNAMES=NO, and then set the names yourself.
If it is in some way predictable (such as it is "MYDYNAMIC_XXXX" where XXXX changes in some fashion), you can probably figure it out from dictionary.columns. (Modify libname/memname/etc. as appropriate; memname is the dataset name.)
proc sql;
select name into :dynname
from dictionary.columns
where libname='WORK' and memname='MYDATASET'
and name like 'MYDYNAMIC_%';
quit;
Alternately, you could use a NOT(IN(...)) clause to eliminate the known column names, if you need to know that.
Finally, if it is in one consistent location, easier than using GETNAMES=NO may be to query dictionary.columns based on the variable number (where varnum=5 for example if it is the fifth variable number).
Expanding on Joe's last comment - is the column is in the same position, just called something different?
If so, you can use the dictionary.columns table, selecting the specific column number, and storing the corresponding column name in a macro variable.
Example, your column is the 5th column in Excel/dataset...
/* Pull column name */
proc sql ;
select name into :DYNVAR
from dictionary.columns
where libname = 'SASHELP'
and memname = 'CLASS'
and varnum = 5 ;
quit ;
/* Then to reference the column simply substitute it for &DYNVAR */
data want ;
set sashelp.class (keep=&DYNVAR) ;
run ;
You could then extend this to multiple columns if necessary...
/* Pull column name */
proc sql ;
select name into :DYNVARS separated by ' '
from dictionary.columns
where libname = 'SASHELP'
and memname = 'CLASS'
and varnum in (1,4,5) ;
quit ;
/* Then to reference the columns simply substitute it for &DYNVARS */
data want ;
set sashelp.class (keep=&DYNVARS) ;
run ;